';
viewerComponents['epub'].onFirstLoad = function(container){
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("xmldom"), (function webpackLoadOptionalExternalModule() { try { return require("jszip"); } catch(e) {} }()));
else if(typeof define === 'function' && define.amd)
define(["xmldom", "jszip"], factory);
else if(typeof exports === 'object')
exports["ePub"] = factory(require("xmldom"), (function webpackLoadOptionalExternalModule() { try { return require("jszip"); } catch(e) {} }()));
else
root["ePub"] = factory(root["xmldom"], root["jszip"]);
})(typeof self !== 'undefined' ? self : this, function(__WEBPACK_EXTERNAL_MODULE_42__, __WEBPACK_EXTERNAL_MODULE_73__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "/dist/";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 25);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i -1) {
return true;
}
return Math.floor(f) !== f;
}
/**
* Get a prefixed css property
* @param {string} unprefixed
* @returns {string}
* @memberof Core
*/
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 b) return 1;
if (a = 0 ? pivot : pivot + 1;
}
if (compared === 0) {
return pivot;
}
if (compared === -1) {
return locationOf(item, array, compareFunction, pivot, end);
} else {
return locationOf(item, array, compareFunction, start, pivot);
}
}
/**
* Finds index of something in a sorted array
* Returns -1 if not found
* @param {any} item
* @param {array} array
* @param {function} [compareFunction]
* @param {function} [_start]
* @param {function} [_end]
* @returns {number} index (in array) or -1
* @memberof Core
*/
function indexOfSorted(item, array, compareFunction, _start, _end) {
var start = _start || 0;
var end = _end || array.length;
var pivot = parseInt(start + (end - start) / 2);
var compared;
if (!compareFunction) {
compareFunction = function compareFunction(a, b) {
if (a > b) return 1;
if (a -1;
}
/**
* Create a new blob
* @param {any} content
* @param {string} mime
* @returns {Blob}
* @memberof Core
*/
function createBlob(content, mime) {
return new Blob([content], { type: mime });
}
/**
* Create a new blob url
* @param {any} content
* @param {string} mime
* @returns {string} url
* @memberof Core
*/
function createBlobUrl(content, mime) {
var tempUrl;
var blob = createBlob(content, mime);
tempUrl = _URL.createObjectURL(blob);
return tempUrl;
}
/**
* Remove a blob url
* @param {string} url
* @memberof Core
*/
function revokeBlobUrl(url) {
return _URL.revokeObjectURL(url);
}
/**
* Create a new base64 encoded url
* @param {any} content
* @param {string} mime
* @returns {string} url
* @memberof Core
*/
function createBase64Url(content, mime) {
var data;
var datauri;
if (typeof content !== "string") {
// Only handles strings
return;
}
data = btoa(encodeURIComponent(content));
datauri = "data:" + mime + ";base64," + data;
return datauri;
}
/**
* Get type of an object
* @param {object} obj
* @returns {string} type
* @memberof Core
*/
function type(obj) {
return Object.prototype.toString.call(obj).slice(8, -1);
}
/**
* Parse xml (or html) markup
* @param {string} markup
* @param {string} mime
* @param {boolean} forceXMLDom force using xmlDom to parse instead of native parser
* @returns {document} document
* @memberof Core
*/
function parse(markup, mime, forceXMLDom) {
var doc;
var Parser;
if (typeof DOMParser === "undefined" || forceXMLDom) {
Parser = __webpack_require__(42).DOMParser;
} else {
Parser = DOMParser;
}
// Remove byte order mark before parsing
// https://www.w3.org/International/questions/qa-byte-order-mark
if (markup.charCodeAt(0) === 0xFEFF) {
markup = markup.slice(1);
}
doc = new Parser().parseFromString(markup, mime);
return doc;
}
/**
* querySelector polyfill
* @param {element} el
* @param {string} sel selector string
* @returns {element} element
* @memberof Core
*/
function qs(el, sel) {
var elements;
if (!el) {
throw new Error("No Element Provided");
}
if (typeof el.querySelector != "undefined") {
return el.querySelector(sel);
} else {
elements = el.getElementsByTagName(sel);
if (elements.length) {
return elements[0];
}
}
}
/**
* querySelectorAll polyfill
* @param {element} el
* @param {string} sel selector string
* @returns {element[]} elements
* @memberof Core
*/
function qsa(el, sel) {
if (typeof el.querySelector != "undefined") {
return el.querySelectorAll(sel);
} else {
return el.getElementsByTagName(sel);
}
}
/**
* querySelector by property
* @param {element} el
* @param {string} sel selector string
* @param {object[]} props
* @returns {element[]} elements
* @memberof Core
*/
function qsp(el, sel, props) {
var q, filtered;
if (typeof el.querySelector != "undefined") {
sel += "[";
for (var prop in props) {
sel += prop + "~='" + props[prop] + "'";
}
sel += "]";
return el.querySelector(sel);
} else {
q = el.getElementsByTagName(sel);
filtered = Array.prototype.slice.call(q, 0).filter(function (el) {
for (var prop in props) {
if (el.getAttribute(prop) === props[prop]) {
return true;
}
}
return false;
});
if (filtered) {
return filtered[0];
}
}
}
/**
* Sprint through all text nodes in a document
* @memberof Core
* @param {element} root element to start with
* @param {function} func function to run on each element
*/
function sprint(root, func) {
var doc = root.ownerDocument || root;
if (typeof doc.createTreeWalker !== "undefined") {
treeWalker(root, func, NodeFilter.SHOW_TEXT);
} else {
walk(root, function (node) {
if (node && node.nodeType === 3) {
// Node.TEXT_NODE
func(node);
}
}, true);
}
}
/**
* Create a treeWalker
* @memberof Core
* @param {element} root element to start with
* @param {function} func function to run on each element
* @param {function | object} filter funtion or object to filter with
*/
function treeWalker(root, func, filter) {
var treeWalker = document.createTreeWalker(root, filter, null, false);
var node = void 0;
while (node = treeWalker.nextNode()) {
func(node);
}
}
/**
* @memberof Core
* @param {node} node
* @param {callback} return false for continue,true for break inside callback
*/
function walk(node, callback) {
if (callback(node)) {
return true;
}
node = node.firstChild;
if (node) {
do {
var walked = walk(node, callback);
if (walked) {
return true;
}
node = node.nextSibling;
} while (node);
}
}
/**
* Convert a blob to a base64 encoded string
* @param {Blog} blob
* @returns {string}
* @memberof Core
*/
function blob2base64(blob) {
return new Promise(function (resolve, reject) {
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function () {
resolve(reader.result);
};
});
}
/**
* Creates a new pending promise and provides methods to resolve or reject it.
* From: https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Deferred#backwards_forwards_compatible
* @memberof Core
*/
function defer() {
var _this = this;
/* A method to resolve the associated Promise with the value passed.
* If the promise is already settled it does nothing.
*
* @param {anything} value : This value is used to resolve the promise
* If the value is a Promise then the associated promise assumes the state
* of Promise passed as value.
*/
this.resolve = null;
/* A method to reject the assocaited Promise with the value passed.
* If the promise is already settled it does nothing.
*
* @param {anything} reason: The reason for the rejection of the Promise.
* Generally its an Error object. If however a Promise is passed, then the Promise
* itself will be the reason for rejection no matter the state of the Promise.
*/
this.reject = null;
this.id = uuid();
/* A newly created Pomise object.
* Initially in pending state.
*/
this.promise = new Promise(function (resolve, reject) {
_this.resolve = resolve;
_this.reject = reject;
});
Object.freeze(this);
}
/**
* querySelector with filter by epub type
* @param {element} html
* @param {string} element element type to find
* @param {string} type epub type to find
* @returns {element[]} elements
* @memberof Core
*/
function querySelectorByType(html, element, type) {
var query;
if (typeof html.querySelector != "undefined") {
query = html.querySelector(element + "[*|type=\"" + type + "\"]");
}
// Handle IE not supporting namespaced epub:type in querySelector
if (!query || query.length === 0) {
query = qsa(html, element);
for (var i = 0; i 1) {
terminal = parts[1];
component.terminal = this.parseTerminal(terminal);
}
if (steps[0] === "") {
steps.shift(); // Ignore the first slash
}
component.steps = steps.map(function (step) {
return this.parseStep(step);
}.bind(this));
return component;
}
}, {
key: "parseStep",
value: function parseStep(stepStr) {
var type, num, index, has_brackets, id;
has_brackets = stepStr.match(/\[(.*)\]/);
if (has_brackets && has_brackets[1]) {
id = has_brackets[1];
}
//-- Check if step is a text node or element
num = parseInt(stepStr);
if (isNaN(num)) {
return;
}
if (num % 2 === 0) {
// Even = is an element
type = "element";
index = num / 2 - 1;
} else {
type = "text";
index = (num - 1) / 2;
}
return {
"type": type,
"index": index,
"id": id || null
};
}
}, {
key: "parseTerminal",
value: function parseTerminal(termialStr) {
var characterOffset, textLocationAssertion;
var assertion = termialStr.match(/\[(.*)\]/);
if (assertion && assertion[1]) {
characterOffset = parseInt(termialStr.split("[")[0]);
textLocationAssertion = assertion[1];
} else {
characterOffset = parseInt(termialStr);
}
if (!(0, _core.isNumber)(characterOffset)) {
characterOffset = null;
}
return {
"offset": characterOffset,
"assertion": textLocationAssertion
};
}
}, {
key: "getChapterComponent",
value: function getChapterComponent(cfiStr) {
var indirection = cfiStr.split("!");
return indirection[0];
}
}, {
key: "getPathComponent",
value: function getPathComponent(cfiStr) {
var indirection = cfiStr.split("!");
if (indirection[1]) {
var ranges = indirection[1].split(",");
return ranges[0];
}
}
}, {
key: "getRange",
value: function getRange(cfiStr) {
var ranges = cfiStr.split(",");
if (ranges.length === 3) {
return [ranges[1], ranges[2]];
}
return false;
}
}, {
key: "getCharecterOffsetComponent",
value: function getCharecterOffsetComponent(cfiStr) {
var splitStr = cfiStr.split(":");
return splitStr[1] || "";
}
}, {
key: "joinSteps",
value: function joinSteps(steps) {
if (!steps) {
return "";
}
return steps.map(function (part) {
var segment = "";
if (part.type === "element") {
segment += (part.index + 1) * 2;
}
if (part.type === "text") {
segment += 1 + 2 * part.index; // TODO: double check that this is odd
}
if (part.id) {
segment += "[" + part.id + "]";
}
return segment;
}).join("/");
}
}, {
key: "segmentString",
value: function segmentString(segment) {
var segmentString = "/";
segmentString += this.joinSteps(segment.steps);
if (segment.terminal && segment.terminal.offset != null) {
segmentString += ":" + segment.terminal.offset;
}
if (segment.terminal && segment.terminal.assertion != null) {
segmentString += "[" + segment.terminal.assertion + "]";
}
return segmentString;
}
/**
* Convert CFI to a epubcfi(...) string
* @returns {string} epubcfi
*/
}, {
key: "toString",
value: function toString() {
var cfiString = "epubcfi(";
cfiString += this.segmentString(this.base);
cfiString += "!";
cfiString += this.segmentString(this.path);
// Add Range, if present
if (this.range && this.start) {
cfiString += ",";
cfiString += this.segmentString(this.start);
}
if (this.range && this.end) {
cfiString += ",";
cfiString += this.segmentString(this.end);
}
cfiString += ")";
return cfiString;
}
/**
* Compare which of two CFIs is earlier in the text
* @returns {number} First is earlier = -1, Second is earlier = 1, They are equal = 0
*/
}, {
key: "compare",
value: function compare(cfiOne, cfiTwo) {
var stepsA, stepsB;
var terminalA, terminalB;
var rangeAStartSteps, rangeAEndSteps;
var rangeBEndSteps, rangeBEndSteps;
var rangeAStartTerminal, rangeAEndTerminal;
var rangeBStartTerminal, rangeBEndTerminal;
if (typeof cfiOne === "string") {
cfiOne = new EpubCFI(cfiOne);
}
if (typeof cfiTwo === "string") {
cfiTwo = new EpubCFI(cfiTwo);
}
// Compare Spine Positions
if (cfiOne.spinePos > cfiTwo.spinePos) {
return 1;
}
if (cfiOne.spinePos stepsB[i].index) {
return 1;
}
if (stepsA[i].index terminalB.offset) {
return 1;
}
if (terminalA.offset = 0) {
segment.terminal.offset = offset;
// Make sure we are getting to a textNode if there is an offset
if (segment.steps[segment.steps.length - 1].type != "text") {
segment.steps.push({
"type": "text",
"index": 0
});
}
}
return segment;
}
}, {
key: "equalStep",
value: function equalStep(stepA, stepB) {
if (!stepA || !stepB) {
return false;
}
if (stepA.index === stepB.index && stepA.id === stepB.id && stepA.type === stepB.type) {
return true;
}
return false;
}
/**
* Create a CFI object from a Range
* @param {Range} range
* @param {string | object} base
* @param {string} [ignoreClass]
* @returns {object} cfi
*/
}, {
key: "fromRange",
value: function fromRange(range, base, ignoreClass) {
var cfi = {
range: false,
base: {},
path: {},
start: null,
end: null
};
var start = range.startContainer;
var end = range.endContainer;
var startOffset = range.startOffset;
var endOffset = range.endOffset;
var needsIgnoring = false;
if (ignoreClass) {
// Tell pathTo if / what to ignore
needsIgnoring = start.ownerDocument.querySelector("." + ignoreClass) != null;
}
if (typeof base === "string") {
cfi.base = this.parseComponent(base);
cfi.spinePos = cfi.base.steps[1].index;
} else if ((typeof base === "undefined" ? "undefined" : _typeof(base)) === "object") {
cfi.base = base;
}
if (range.collapsed) {
if (needsIgnoring) {
startOffset = this.patchOffset(start, startOffset, ignoreClass);
}
cfi.path = this.pathTo(start, startOffset, ignoreClass);
} else {
cfi.range = true;
if (needsIgnoring) {
startOffset = this.patchOffset(start, startOffset, ignoreClass);
}
cfi.start = this.pathTo(start, startOffset, ignoreClass);
if (needsIgnoring) {
endOffset = this.patchOffset(end, endOffset, ignoreClass);
}
cfi.end = this.pathTo(end, endOffset, ignoreClass);
// Create a new empty path
cfi.path = {
steps: [],
terminal: null
};
// Push steps that are shared between start and end to the common path
var len = cfi.start.steps.length;
var i;
for (i = 0; i 0 && currNodeType === TEXT_NODE && prevNodeType === TEXT_NODE) {
// join text nodes
output[i] = prevIndex;
} else if (nodeType === currNodeType) {
prevIndex = prevIndex + 1;
output[i] = prevIndex;
}
prevNodeType = currNodeType;
}
return output;
}
}, {
key: "position",
value: function position(anchor) {
var children, index;
if (anchor.nodeType === ELEMENT_NODE) {
children = anchor.parentNode.children;
if (!children) {
children = (0, _core.findChildren)(anchor.parentNode);
}
index = Array.prototype.indexOf.call(children, anchor);
} else {
children = this.textNodes(anchor.parentNode);
index = children.indexOf(anchor);
}
return index;
}
}, {
key: "filteredPosition",
value: function filteredPosition(anchor, ignoreClass) {
var children, index, map;
if (anchor.nodeType === ELEMENT_NODE) {
children = anchor.parentNode.children;
map = this.normalizedMap(children, ELEMENT_NODE, ignoreClass);
} else {
children = anchor.parentNode.childNodes;
// Inside an ignored node
if (anchor.parentNode.classList.contains(ignoreClass)) {
anchor = anchor.parentNode;
children = anchor.parentNode.childNodes;
}
map = this.normalizedMap(children, TEXT_NODE, ignoreClass);
}
index = Array.prototype.indexOf.call(children, anchor);
return map[index];
}
}, {
key: "stepsToXpath",
value: function stepsToXpath(steps) {
var xpath = [".", "*"];
steps.forEach(function (step) {
var position = step.index + 1;
if (step.id) {
xpath.push("*[position()=" + position + " and @id='" + step.id + "']");
} else if (step.type === "text") {
xpath.push("text()[" + position + "]");
} else {
xpath.push("*[" + position + "]");
}
});
return xpath.join("/");
}
/*
To get the last step if needed:
// Get the terminal step
lastStep = steps[steps.length-1];
// Get the query string
query = this.stepsToQuery(steps);
// Find the containing element
startContainerParent = doc.querySelector(query);
// Find the text node within that element
if(startContainerParent && lastStep.type == "text") {
container = startContainerParent.childNodes[lastStep.index];
}
*/
}, {
key: "stepsToQuerySelector",
value: function stepsToQuerySelector(steps) {
var query = ["html"];
steps.forEach(function (step) {
var position = step.index + 1;
if (step.id) {
query.push("#" + step.id);
} else if (step.type === "text") {
// unsupported in querySelector
// query.push("text()[" + position + "]");
} else {
query.push("*:nth-child(" + position + ")");
}
});
return query.join(">");
}
}, {
key: "textNodes",
value: function textNodes(container, ignoreClass) {
return Array.prototype.slice.call(container.childNodes).filter(function (node) {
if (node.nodeType === TEXT_NODE) {
return true;
} else if (ignoreClass && node.classList.contains(ignoreClass)) {
return true;
}
return false;
});
}
}, {
key: "walkToNode",
value: function walkToNode(steps, _doc, ignoreClass) {
var doc = _doc || document;
var container = doc.documentElement;
var children;
var step;
var len = steps.length;
var i;
for (i = 0; i len) {
offset = offset - len;
} else {
if (child.nodeType === ELEMENT_NODE) {
container = child.childNodes[0];
} else {
container = child;
}
break;
}
}
}
return {
container: container,
offset: offset
};
}
/**
* Creates a DOM range representing a CFI
* @param {document} _doc document referenced in the base
* @param {string} [ignoreClass]
* @return {Range}
*/
}, {
key: "toRange",
value: function toRange(_doc, ignoreClass) {
var doc = _doc || document;
var range;
var start, end, startContainer, endContainer;
var cfi = this;
var startSteps, endSteps;
var needsIgnoring = ignoreClass ? doc.querySelector("." + ignoreClass) != null : false;
var missed;
if (typeof doc.createRange !== "undefined") {
range = doc.createRange();
} else {
range = new _core.RangeObject();
}
if (cfi.range) {
start = cfi.start;
startSteps = cfi.path.steps.concat(start.steps);
startContainer = this.findNode(startSteps, doc, needsIgnoring ? ignoreClass : null);
end = cfi.end;
endSteps = cfi.path.steps.concat(end.steps);
endContainer = this.findNode(endSteps, doc, needsIgnoring ? ignoreClass : null);
} else {
start = cfi.path;
startSteps = cfi.path.steps;
startContainer = this.findNode(cfi.path.steps, doc, needsIgnoring ? ignoreClass : null);
}
if (startContainer) {
try {
if (start.terminal.offset != null) {
range.setStart(startContainer, start.terminal.offset);
} else {
range.setStart(startContainer, 0);
}
} catch (e) {
missed = this.fixMiss(startSteps, start.terminal.offset, doc, needsIgnoring ? ignoreClass : null);
range.setStart(missed.container, missed.offset);
}
} else {
console.log("No startContainer found for", this.toString());
// No start found
return null;
}
if (endContainer) {
try {
if (end.terminal.offset != null) {
range.setEnd(endContainer, end.terminal.offset);
} else {
range.setEnd(endContainer, 0);
}
} catch (e) {
missed = this.fixMiss(endSteps, cfi.end.terminal.offset, doc, needsIgnoring ? ignoreClass : null);
range.setEnd(missed.container, missed.offset);
}
}
// doc.defaultView.getSelection().addRange(range);
return range;
}
/**
* Check if a string is wrapped with "epubcfi()"
* @param {string} str
* @returns {boolean}
*/
}, {
key: "isCfiString",
value: function isCfiString(str) {
if (typeof str === "string" && str.indexOf("epubcfi(") === 0 && str[str.length - 1] === ")") {
return true;
}
return false;
}
}, {
key: "generateChapterComponent",
value: function generateChapterComponent(_spineNodeIndex, _pos, id) {
var pos = parseInt(_pos),
spineNodeIndex = (_spineNodeIndex + 1) * 2,
cfi = "/" + spineNodeIndex + "/";
cfi += (pos + 1) * 2;
if (id) {
cfi += "[" + id + "]";
}
return cfi;
}
/**
* Collapse a CFI Range to a single CFI Position
* @param {boolean} [toStart=false]
*/
}, {
key: "collapse",
value: function collapse(toStart) {
if (!this.range) {
return;
}
this.range = false;
if (toStart) {
this.path.steps = this.path.steps.concat(this.start.steps);
this.path.terminal = this.start.terminal;
} else {
this.path.steps = this.path.steps.concat(this.end.steps);
this.path.terminal = this.end.terminal;
}
}
}]);
return EpubCFI;
}();
exports.default = EpubCFI;
module.exports = exports["default"];
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var EPUBJS_VERSION = exports.EPUBJS_VERSION = "0.3";
// Dom events to listen for
var DOM_EVENTS = exports.DOM_EVENTS = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click", "touchend", "touchstart", "touchmove"];
var EVENTS = exports.EVENTS = {
BOOK: {
OPEN_FAILED: "openFailed"
},
CONTENTS: {
EXPAND: "expand",
RESIZE: "resize",
SELECTED: "selected",
SELECTED_RANGE: "selectedRange",
LINK_CLICKED: "linkClicked"
},
LOCATIONS: {
CHANGED: "changed"
},
MANAGERS: {
RESIZE: "resize",
RESIZED: "resized",
ORIENTATION_CHANGE: "orientationchange",
ADDED: "added",
SCROLL: "scroll",
SCROLLED: "scrolled",
REMOVED: "removed"
},
VIEWS: {
AXIS: "axis",
LOAD_ERROR: "loaderror",
RENDERED: "rendered",
RESIZED: "resized",
DISPLAYED: "displayed",
SHOWN: "shown",
HIDDEN: "hidden",
MARK_CLICKED: "markClicked"
},
RENDITION: {
STARTED: "started",
ATTACHED: "attached",
DISPLAYED: "displayed",
DISPLAY_ERROR: "displayerror",
RENDERED: "rendered",
REMOVED: "removed",
RESIZED: "resized",
ORIENTATION_CHANGE: "orientationchange",
LOCATION_CHANGED: "locationChanged",
RELOCATED: "relocated",
MARK_CLICKED: "markClicked",
SELECTED: "selected",
LAYOUT: "layout"
},
LAYOUT: {
UPDATED: "updated"
},
ANNOTATION: {
ATTACH: "attach",
DETACH: "detach"
}
};
/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var d = __webpack_require__(27)
, callable = __webpack_require__(41)
, apply = Function.prototype.apply, call = Function.prototype.call
, create = Object.create, defineProperty = Object.defineProperty
, defineProperties = Object.defineProperties
, hasOwnProperty = Object.prototype.hasOwnProperty
, descriptor = { configurable: true, enumerable: false, writable: true }
, on, once, off, emit, methods, descriptors, base;
on = function (type, listener) {
var data;
callable(listener);
if (!hasOwnProperty.call(this, '__ee__')) {
data = descriptor.value = create(null);
defineProperty(this, '__ee__', descriptor);
descriptor.value = null;
} else {
data = this.__ee__;
}
if (!data[type]) data[type] = listener;
else if (typeof data[type] === 'object') data[type].push(listener);
else data[type] = [data[type], listener];
return this;
};
once = function (type, listener) {
var once, self;
callable(listener);
self = this;
on.call(this, type, once = function () {
off.call(self, type, once);
apply.call(listener, this, arguments);
});
once.__eeOnceListener__ = listener;
return this;
};
off = function (type, listener) {
var data, listeners, candidate, i;
callable(listener);
if (!hasOwnProperty.call(this, '__ee__')) return this;
data = this.__ee__;
if (!data[type]) return this;
listeners = data[type];
if (typeof listeners === 'object') {
for (i = 0; (candidate = listeners[i]); ++i) {
if ((candidate === listener) ||
(candidate.__eeOnceListener__ === listener)) {
if (listeners.length === 2) data[type] = listeners[i ? 0 : 1];
else listeners.splice(i, 1);
}
}
} else {
if ((listeners === listener) ||
(listeners.__eeOnceListener__ === listener)) {
delete data[type];
}
}
return this;
};
emit = function (type) {
var i, l, listener, listeners, args;
if (!hasOwnProperty.call(this, '__ee__')) return;
listeners = this.__ee__[type];
if (!listeners) return;
if (typeof listeners === 'object') {
l = arguments.length;
args = new Array(l - 1);
for (i = 1; i -1) {
pathString = new URL(pathString).pathname;
}
parsed = this.parse(pathString);
this.path = pathString;
if (this.isDirectory(pathString)) {
this.directory = pathString;
} else {
this.directory = parsed.dir + "/";
}
this.filename = parsed.base;
this.extension = parsed.ext.slice(1);
}
/**
* Parse the path: https://nodejs.org/api/path.html#path_path_parse_path
* @param {string} what
* @returns {object}
*/
_createClass(Path, [{
key: "parse",
value: function parse(what) {
return _pathWebpack2.default.parse(what);
}
/**
* @param {string} what
* @returns {boolean}
*/
}, {
key: "isAbsolute",
value: function isAbsolute(what) {
return _pathWebpack2.default.isAbsolute(what || this.path);
}
/**
* Check if path ends with a directory
* @param {string} what
* @returns {boolean}
*/
}, {
key: "isDirectory",
value: function isDirectory(what) {
return what.charAt(what.length - 1) === "/";
}
/**
* Resolve a path against the directory of the Path
*
* https://nodejs.org/api/path.html#path_path_resolve_paths
* @param {string} what
* @returns {string} resolved
*/
}, {
key: "resolve",
value: function resolve(what) {
return _pathWebpack2.default.resolve(this.directory, what);
}
/**
* Resolve a path relative to the directory of the Path
*
* https://nodejs.org/api/path.html#path_path_relative_from_to
* @param {string} what
* @returns {string} relative
*/
}, {
key: "relative",
value: function relative(what) {
var isAbsolute = what && what.indexOf("://") > -1;
if (isAbsolute) {
return what;
}
return _pathWebpack2.default.relative(this.directory, what);
}
}, {
key: "splitPath",
value: function splitPath(filename) {
return this.splitPathRe.exec(filename).slice(1);
}
/**
* Return the path string
* @returns {string} path
*/
}, {
key: "toString",
value: function toString() {
return this.path;
}
}]);
return Path;
}();
exports.default = Path;
module.exports = exports["default"];
/***/ }),
/* 5 */
/***/ (function(module, exports) {
var g;
// This works in non-strict mode
g = (function() {
return this;
})();
try {
// This works if eval is allowed (see CSP)
g = g || Function("return this")() || (1,eval)("this");
} catch(e) {
// This works if the window reference is available
if(typeof window === "object")
g = window;
}
// g can still be undefined, but nothing to do about it...
// We return undefined, instead of nothing here, so it's
// easier to handle this case. if(!global) { ...}
module.exports = g;
/***/ }),
/* 6 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i -1;
var pathname = urlString;
var basePath;
this.Url = undefined;
this.href = urlString;
this.protocol = "";
this.origin = "";
this.hash = "";
this.hash = "";
this.search = "";
this.base = baseString;
if (!absolute && baseString !== false && typeof baseString !== "string" && window && window.location) {
this.base = window.location.href;
}
// URL Polyfill doesn't throw an error if base is empty
if (absolute || this.base) {
try {
if (this.base) {
// Safari doesn't like an undefined base
this.Url = new URL(urlString, this.base);
} else {
this.Url = new URL(urlString);
}
this.href = this.Url.href;
this.protocol = this.Url.protocol;
this.origin = this.Url.origin;
this.hash = this.Url.hash;
this.search = this.Url.search;
pathname = this.Url.pathname + (this.Url.search ? this.Url.search : '');
} catch (e) {
// Skip URL parsing
this.Url = undefined;
// resolve the pathname from the base
if (this.base) {
basePath = new _path2.default(this.base);
pathname = basePath.resolve(pathname);
}
}
}
this.Path = new _path2.default(pathname);
this.directory = this.Path.directory;
this.filename = this.Path.filename;
this.extension = this.Path.extension;
}
/**
* @returns {Path}
*/
_createClass(Url, [{
key: "path",
value: function path() {
return this.Path;
}
/**
* Resolves a relative path to a absolute url
* @param {string} what
* @returns {string} url
*/
}, {
key: "resolve",
value: function resolve(what) {
var isAbsolute = what.indexOf("://") > -1;
var fullpath;
if (isAbsolute) {
return what;
}
fullpath = _pathWebpack2.default.resolve(this.directory, what);
return this.origin + fullpath;
}
/**
* Resolve a path relative to the url
* @param {string} what
* @returns {string} path
*/
}, {
key: "relative",
value: function relative(what) {
return _pathWebpack2.default.relative(what, this.directory);
}
/**
* @returns {string}
*/
}, {
key: "toString",
value: function toString() {
return this.href;
}
}]);
return Url;
}();
exports.default = Url;
module.exports = exports["default"];
/***/ }),
/* 7 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
if (!process) {
var process = {
"cwd" : function () { return '/' }
};
}
function assertPath(path) {
if (typeof path !== 'string') {
throw new TypeError('Path must be a string. Received ' + path);
}
}
// Resolves . and .. elements in a path with directory names
function normalizeStringPosix(path, allowAboveRoot) {
var res = '';
var lastSlash = -1;
var dots = 0;
var code;
for (var i = 0; i 2) {
var start = res.length - 1;
var j = start;
for (; j >= 0; --j) {
if (res.charCodeAt(j) === 47/*/*/)
break;
}
if (j !== start) {
if (j === -1)
res = '';
else
res = res.slice(0, j);
lastSlash = i;
dots = 0;
continue;
}
} else if (res.length === 2 || res.length === 1) {
res = '';
lastSlash = i;
dots = 0;
continue;
}
}
if (allowAboveRoot) {
if (res.length > 0)
res += '/..';
else
res = '..';
}
} else {
if (res.length > 0)
res += '/' + path.slice(lastSlash + 1, i);
else
res = path.slice(lastSlash + 1, i);
}
lastSlash = i;
dots = 0;
} else if (code === 46/*.*/ && dots !== -1) {
++dots;
} else {
dots = -1;
}
}
return res;
}
function _format(sep, pathObject) {
var dir = pathObject.dir || pathObject.root;
var base = pathObject.base ||
((pathObject.name || '') + (pathObject.ext || ''));
if (!dir) {
return base;
}
if (dir === pathObject.root) {
return dir + base;
}
return dir + sep + base;
}
var posix = {
// path.resolve([from ...], to)
resolve: function resolve() {
var resolvedPath = '';
var resolvedAbsolute = false;
var cwd;
for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
var path;
if (i >= 0)
path = arguments[i];
else {
if (cwd === undefined)
cwd = process.cwd();
path = cwd;
}
assertPath(path);
// Skip empty entries
if (path.length === 0) {
continue;
}
resolvedPath = path + '/' + resolvedPath;
resolvedAbsolute = path.charCodeAt(0) === 47/*/*/;
}
// At this point the path should be resolved to a full absolute path, but
// handle relative paths to be safe (might happen when process.cwd() fails)
// Normalize the path
resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute);
if (resolvedAbsolute) {
if (resolvedPath.length > 0)
return '/' + resolvedPath;
else
return '/';
} else if (resolvedPath.length > 0) {
return resolvedPath;
} else {
return '.';
}
},
normalize: function normalize(path) {
assertPath(path);
if (path.length === 0)
return '.';
var isAbsolute = path.charCodeAt(0) === 47/*/*/;
var trailingSeparator = path.charCodeAt(path.length - 1) === 47/*/*/;
// Normalize the path
path = normalizeStringPosix(path, !isAbsolute);
if (path.length === 0 && !isAbsolute)
path = '.';
if (path.length > 0 && trailingSeparator)
path += '/';
if (isAbsolute)
return '/' + path;
return path;
},
isAbsolute: function isAbsolute(path) {
assertPath(path);
return path.length > 0 && path.charCodeAt(0) === 47/*/*/;
},
join: function join() {
if (arguments.length === 0)
return '.';
var joined;
for (var i = 0; i 0) {
if (joined === undefined)
joined = arg;
else
joined += '/' + arg;
}
}
if (joined === undefined)
return '.';
return posix.normalize(joined);
},
relative: function relative(from, to) {
assertPath(from);
assertPath(to);
if (from === to)
return '';
from = posix.resolve(from);
to = posix.resolve(to);
if (from === to)
return '';
// Trim any leading backslashes
var fromStart = 1;
for (; fromStart length) {
if (to.charCodeAt(toStart + i) === 47/*/*/) {
// We get here if `from` is the exact base path for `to`.
// For example: from='/foo/bar'; to='/foo/bar/baz'
return to.slice(toStart + i + 1);
} else if (i === 0) {
// We get here if `from` is the root
// For example: from='/'; to='/foo'
return to.slice(toStart + i);
}
} else if (fromLen > length) {
if (from.charCodeAt(fromStart + i) === 47/*/*/) {
// We get here if `to` is the exact base path for `from`.
// For example: from='/foo/bar/baz'; to='/foo/bar'
lastCommonSep = i;
} else if (i === 0) {
// We get here if `to` is the root.
// For example: from='/foo'; to='/'
lastCommonSep = 0;
}
}
break;
}
var fromCode = from.charCodeAt(fromStart + i);
var toCode = to.charCodeAt(toStart + i);
if (fromCode !== toCode)
break;
else if (fromCode === 47/*/*/)
lastCommonSep = i;
}
var out = '';
// Generate the relative path based on the path difference between `to`
// and `from`
for (i = fromStart + lastCommonSep + 1; i 0)
return out + to.slice(toStart + lastCommonSep);
else {
toStart += lastCommonSep;
if (to.charCodeAt(toStart) === 47/*/*/)
++toStart;
return to.slice(toStart);
}
},
_makeLong: function _makeLong(path) {
return path;
},
dirname: function dirname(path) {
assertPath(path);
if (path.length === 0)
return '.';
var code = path.charCodeAt(0);
var hasRoot = (code === 47/*/*/);
var end = -1;
var matchedSlash = true;
for (var i = path.length - 1; i >= 1; --i) {
code = path.charCodeAt(i);
if (code === 47/*/*/) {
if (!matchedSlash) {
end = i;
break;
}
} else {
// We saw the first non-path separator
matchedSlash = false;
}
}
if (end === -1)
return hasRoot ? '/' : '.';
if (hasRoot && end === 1)
return '//';
return path.slice(0, end);
},
basename: function basename(path, ext) {
if (ext !== undefined && typeof ext !== 'string')
throw new TypeError('"ext" argument must be a string');
assertPath(path);
var start = 0;
var end = -1;
var matchedSlash = true;
var i;
if (ext !== undefined && ext.length > 0 && ext.length = 0; --i) {
var code = path.charCodeAt(i);
if (code === 47/*/*/) {
// If we reached a path separator that was not part of a set of path
// separators at the end of the string, stop now
if (!matchedSlash) {
start = i + 1;
break;
}
} else {
if (firstNonSlashEnd === -1) {
// We saw the first non-path separator, remember this index in case
// we need it if the extension ends up not matching
matchedSlash = false;
firstNonSlashEnd = i + 1;
}
if (extIdx >= 0) {
// Try to match the explicit extension
if (code === ext.charCodeAt(extIdx)) {
if (--extIdx === -1) {
// We matched the extension, so mark this as the end of our path
// component
end = i;
}
} else {
// Extension does not match, so our result is the entire path
// component
extIdx = -1;
end = firstNonSlashEnd;
}
}
}
}
if (start === end)
end = firstNonSlashEnd;
else if (end === -1)
end = path.length;
return path.slice(start, end);
} else {
for (i = path.length - 1; i >= 0; --i) {
if (path.charCodeAt(i) === 47/*/*/) {
// If we reached a path separator that was not part of a set of path
// separators at the end of the string, stop now
if (!matchedSlash) {
start = i + 1;
break;
}
} else if (end === -1) {
// We saw the first non-path separator, mark this as the end of our
// path component
matchedSlash = false;
end = i + 1;
}
}
if (end === -1)
return '';
return path.slice(start, end);
}
},
extname: function extname(path) {
assertPath(path);
var startDot = -1;
var startPart = 0;
var end = -1;
var matchedSlash = true;
// Track the state of characters (if any) we see before our first dot and
// after any path separator we find
var preDotState = 0;
for (var i = path.length - 1; i >= 0; --i) {
var code = path.charCodeAt(i);
if (code === 47/*/*/) {
// If we reached a path separator that was not part of a set of path
// separators at the end of the string, stop now
if (!matchedSlash) {
startPart = i + 1;
break;
}
continue;
}
if (end === -1) {
// We saw the first non-path separator, mark this as the end of our
// extension
matchedSlash = false;
end = i + 1;
}
if (code === 46/*.*/) {
// If this is our first dot, mark it as the start of our extension
if (startDot === -1)
startDot = i;
else if (preDotState !== 1)
preDotState = 1;
} else if (startDot !== -1) {
// We saw a non-dot and non-path separator before our dot, so we should
// have a good chance at having a non-empty extension
preDotState = -1;
}
}
if (startDot === -1 ||
end === -1 ||
// We saw a non-dot character immediately before the dot
preDotState === 0 ||
// The (right-most) trimmed path component is exactly '..'
(preDotState === 1 &&
startDot === end - 1 &&
startDot === startPart + 1)) {
return '';
}
return path.slice(startDot, end);
},
format: function format(pathObject) {
if (pathObject === null || typeof pathObject !== 'object') {
throw new TypeError(
'Parameter "pathObject" must be an object, not ' + typeof(pathObject)
);
}
return _format('/', pathObject);
},
parse: function parse(path) {
assertPath(path);
var ret = { root: '', dir: '', base: '', ext: '', name: '' };
if (path.length === 0)
return ret;
var code = path.charCodeAt(0);
var isAbsolute = (code === 47/*/*/);
var start;
if (isAbsolute) {
ret.root = '/';
start = 1;
} else {
start = 0;
}
var startDot = -1;
var startPart = 0;
var end = -1;
var matchedSlash = true;
var i = path.length - 1;
// Track the state of characters (if any) we see before our first dot and
// after any path separator we find
var preDotState = 0;
// Get non-dir info
for (; i >= start; --i) {
code = path.charCodeAt(i);
if (code === 47/*/*/) {
// If we reached a path separator that was not part of a set of path
// separators at the end of the string, stop now
if (!matchedSlash) {
startPart = i + 1;
break;
}
continue;
}
if (end === -1) {
// We saw the first non-path separator, mark this as the end of our
// extension
matchedSlash = false;
end = i + 1;
}
if (code === 46/*.*/) {
// If this is our first dot, mark it as the start of our extension
if (startDot === -1)
startDot = i;
else if (preDotState !== 1)
preDotState = 1;
} else if (startDot !== -1) {
// We saw a non-dot and non-path separator before our dot, so we should
// have a good chance at having a non-empty extension
preDotState = -1;
}
}
if (startDot === -1 ||
end === -1 ||
// We saw a non-dot character immediately before the dot
preDotState === 0 ||
// The (right-most) trimmed path component is exactly '..'
(preDotState === 1 &&
startDot === end - 1 &&
startDot === startPart + 1)) {
if (end !== -1) {
if (startPart === 0 && isAbsolute)
ret.base = ret.name = path.slice(1, end);
else
ret.base = ret.name = path.slice(startPart, end);
}
} else {
if (startPart === 0 && isAbsolute) {
ret.name = path.slice(1, startDot);
ret.base = path.slice(1, end);
} else {
ret.name = path.slice(startPart, startDot);
ret.base = path.slice(startPart, end);
}
ret.ext = path.slice(startDot, end);
}
if (startPart > 0)
ret.dir = path.slice(0, startPart - 1);
else if (isAbsolute)
ret.dir = '/';
return ret;
},
sep: '/',
delimiter: ':',
posix: null
};
module.exports = posix;
/***/ }),
/* 8 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.replaceBase = replaceBase;
exports.replaceCanonical = replaceCanonical;
exports.replaceMeta = replaceMeta;
exports.replaceLinks = replaceLinks;
exports.substitute = substitute;
var _core = __webpack_require__(0);
var _url = __webpack_require__(6);
var _url2 = _interopRequireDefault(_url);
var _path = __webpack_require__(4);
var _path2 = _interopRequireDefault(_path);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function replaceBase(doc, section) {
var base;
var head;
var url = section.url;
var absolute = url.indexOf("://") > -1;
if (!doc) {
return;
}
head = (0, _core.qs)(doc, "head");
base = (0, _core.qs)(head, "base");
if (!base) {
base = doc.createElement("base");
head.insertBefore(base, head.firstChild);
}
// Fix for Safari crashing if the url doesn't have an origin
if (!absolute && window && window.location) {
url = window.location.origin + url;
}
base.setAttribute("href", url);
}
function replaceCanonical(doc, section) {
var head;
var link;
var url = section.canonical;
if (!doc) {
return;
}
head = (0, _core.qs)(doc, "head");
link = (0, _core.qs)(head, "link[rel='canonical']");
if (link) {
link.setAttribute("href", url);
} else {
link = doc.createElement("link");
link.setAttribute("rel", "canonical");
link.setAttribute("href", url);
head.appendChild(link);
}
}
function replaceMeta(doc, section) {
var head;
var meta;
var id = section.idref;
if (!doc) {
return;
}
head = (0, _core.qs)(doc, "head");
meta = (0, _core.qs)(head, "link[property='dc.identifier']");
if (meta) {
meta.setAttribute("content", id);
} else {
meta = doc.createElement("meta");
meta.setAttribute("name", "dc.identifier");
meta.setAttribute("content", id);
head.appendChild(meta);
}
}
// TODO: move me to Contents
function replaceLinks(contents, fn) {
var links = contents.querySelectorAll("a[href]");
if (!links.length) {
return;
}
var base = (0, _core.qs)(contents.ownerDocument, "base");
var location = base ? base.getAttribute("href") : undefined;
var replaceLink = function (link) {
var href = link.getAttribute("href");
if (href.indexOf("mailto:") === 0) {
return;
}
var absolute = href.indexOf("://") > -1;
if (absolute) {
link.setAttribute("target", "_blank");
} else {
var linkUrl;
try {
linkUrl = new _url2.default(href, location);
} catch (error) {
// NOOP
}
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
*/
if ($viewport && $viewport.hasAttribute("content")) {
var content = $viewport.getAttribute("content");
var _width2 = content.match(/width\s*=\s*([^,]*)/);
var _height2 = content.match(/height\s*=\s*([^,]*)/);
var _scale2 = content.match(/initial-scale\s*=\s*([^,]*)/);
var _minimum2 = content.match(/minimum-scale\s*=\s*([^,]*)/);
var _maximum2 = content.match(/maximum-scale\s*=\s*([^,]*)/);
var _scalable2 = content.match(/user-scalable\s*=\s*([^,]*)/);
if (_width2 && _width2.length && typeof _width2[1] !== "undefined") {
parsed.width = _width2[1];
}
if (_height2 && _height2.length && typeof _height2[1] !== "undefined") {
parsed.height = _height2[1];
}
if (_scale2 && _scale2.length && typeof _scale2[1] !== "undefined") {
parsed.scale = _scale2[1];
}
if (_minimum2 && _minimum2.length && typeof _minimum2[1] !== "undefined") {
parsed.minimum = _minimum2[1];
}
if (_maximum2 && _maximum2.length && typeof _maximum2[1] !== "undefined") {
parsed.maximum = _maximum2[1];
}
if (_scalable2 && _scalable2.length && typeof _scalable2[1] !== "undefined") {
parsed.scalable = _scalable2[1];
}
}
settings = (0, _core.defaults)(options || {}, parsed);
if (options) {
if (settings.width) {
newContent.push("width=" + settings.width);
}
if (settings.height) {
newContent.push("height=" + settings.height);
}
if (settings.scale) {
newContent.push("initial-scale=" + settings.scale);
}
if (settings.scalable === "no") {
newContent.push("minimum-scale=" + settings.scale);
newContent.push("maximum-scale=" + settings.scale);
newContent.push("user-scalable=" + settings.scalable);
} else {
if (settings.scalable) {
newContent.push("user-scalable=" + settings.scalable);
}
if (settings.minimum) {
newContent.push("minimum-scale=" + settings.minimum);
}
if (settings.maximum) {
newContent.push("minimum-scale=" + settings.maximum);
}
}
if (!$viewport) {
$viewport = this.document.createElement("meta");
$viewport.setAttribute("name", "viewport");
this.document.querySelector("head").appendChild($viewport);
}
$viewport.setAttribute("content", newContent.join(", "));
this.window.scrollTo(0, 0);
}
return settings;
}
/**
* Event emitter for when the contents has expanded
* @private
*/
}, {
key: "expand",
value: function expand() {
this.emit(_constants.EVENTS.CONTENTS.EXPAND);
}
/**
* Add DOM listeners
* @private
*/
}, {
key: "listeners",
value: function listeners() {
this.imageLoadListeners();
this.mediaQueryListeners();
// this.fontLoadListeners();
this.addEventListeners();
this.addSelectionListeners();
// this.transitionListeners();
this.resizeListeners();
// this.resizeObservers();
this.linksHandler();
}
/**
* Remove DOM listeners
* @private
*/
}, {
key: "removeListeners",
value: function removeListeners() {
this.removeEventListeners();
this.removeSelectionListeners();
clearTimeout(this.expanding);
}
/**
* Check if size of contents has changed and
* emit 'resize' event if it has.
* @private
*/
}, {
key: "resizeCheck",
value: function resizeCheck() {
var width = this.textWidth();
var height = this.textHeight();
if (width != this._size.width || height != this._size.height) {
this._size = {
width: width,
height: height
};
this.onResize && this.onResize(this._size);
this.emit(_constants.EVENTS.CONTENTS.RESIZE, this._size);
}
}
/**
* Poll for resize detection
* @private
*/
}, {
key: "resizeListeners",
value: function resizeListeners() {
var width, height;
// Test size again
clearTimeout(this.expanding);
requestAnimationFrame(this.resizeCheck.bind(this));
}
/**
* Use css transitions to detect resize
* @private
*/
}, {
key: "transitionListeners",
value: function transitionListeners() {
var body = this.content;
body.style['transitionProperty'] = "font, font-size, font-size-adjust, font-stretch, font-variation-settings, font-weight, width, height";
body.style['transitionDuration'] = "0.001ms";
body.style['transitionTimingFunction'] = "linear";
body.style['transitionDelay'] = "0";
this._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
*/
}, {
key: "mediaQueryListeners",
value: function mediaQueryListeners() {
var sheets = this.document.styleSheets;
var mediaChangeHandler = function (m) {
if (m.matches && !this._expanding) {
setTimeout(this.expand.bind(this), 1);
}
}.bind(this);
for (var i = 0; i 0) {
newRange.setStart(container, range.startOffset - 2);
newRange.setEnd(container, range.startOffset);
position = newRange.getBoundingClientRect();
} else {
// empty, return the parent element
position = container.parentNode.getBoundingClientRect();
}
} catch (e) {
console.error(e, e.stack);
}
} else {
position = range.getBoundingClientRect();
}
}
}
} else if (typeof target === "string" && target.indexOf("#") > -1) {
var id = target.substring(target.indexOf("#") + 1);
var el = this.document.getElementById(id);
if (el) {
if (isWebkit) {
// Webkit reports incorrect bounding rects in Columns
var _newRange = new Range();
_newRange.selectNode(el);
position = _newRange.getBoundingClientRect();
} else {
position = el.getBoundingClientRect();
}
}
}
if (position) {
targetPos.left = position.left;
targetPos.top = position.top;
}
return targetPos;
}
/**
* Append a stylesheet link to the document head
* @param {string} src url
*/
}, {
key: "addStylesheet",
value: function addStylesheet(src) {
return new Promise(function (resolve, reject) {
var $stylesheet;
var ready = false;
if (!this.document) {
resolve(false);
return;
}
// Check if link already exists
$stylesheet = this.document.querySelector("link[href='" + src + "']");
if ($stylesheet) {
resolve(true);
return; // already present
}
$stylesheet = this.document.createElement("link");
$stylesheet.type = "text/css";
$stylesheet.rel = "stylesheet";
$stylesheet.href = src;
$stylesheet.onload = $stylesheet.onreadystatechange = function () {
if (!ready && (!this.readyState || this.readyState == "complete")) {
ready = true;
// Let apply
setTimeout(function () {
resolve(true);
}, 1);
}
};
this.document.head.appendChild($stylesheet);
}.bind(this));
}
}, {
key: "_getStylesheetNode",
value: function _getStylesheetNode(key) {
var styleEl;
key = "epubjs-inserted-css-" + (key || '');
if (!this.document) return false;
// Check if link already exists
styleEl = this.document.getElementById(key);
if (!styleEl) {
styleEl = this.document.createElement("style");
styleEl.id = key;
// Append style element to head
this.document.head.appendChild(styleEl);
}
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
*/
}, {
key: "addStylesheetCss",
value: function 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
*/
}, {
key: "addStylesheetRules",
value: function addStylesheetRules(rules, key) {
var styleSheet;
if (!this.document || !rules || rules.length === 0) return;
// Grab style sheet
styleSheet = this._getStylesheetNode(key).sheet;
if (Object.prototype.toString.call(rules) === "[object Array]") {
for (var i = 0, rl = rules.length; i 0) {
range = selection.getRangeAt(0);
if (!range.collapsed) {
// cfirange = this.section.cfiFromRange(range);
cfirange = new _epubcfi2.default(range, this.cfiBase).toString();
this.emit(_constants.EVENTS.CONTENTS.SELECTED, cfirange);
this.emit(_constants.EVENTS.CONTENTS.SELECTED_RANGE, range);
}
}
}
/**
* Get a Dom Range from EpubCFI
* @param {EpubCFI} _cfi
* @param {string} [ignoreClass]
* @returns {Range} range
*/
}, {
key: "range",
value: function range(_cfi, ignoreClass) {
var cfi = new _epubcfi2.default(_cfi);
return cfi.toRange(this.document, ignoreClass);
}
/**
* Get an EpubCFI from a Dom Range
* @param {Range} range
* @param {string} [ignoreClass]
* @returns {EpubCFI} cfi
*/
}, {
key: "cfiFromRange",
value: function cfiFromRange(range, ignoreClass) {
return new _epubcfi2.default(range, this.cfiBase, ignoreClass).toString();
}
/**
* Get an EpubCFI from a Dom node
* @param {node} node
* @param {string} [ignoreClass]
* @returns {EpubCFI} cfi
*/
}, {
key: "cfiFromNode",
value: function cfiFromNode(node, ignoreClass) {
return new _epubcfi2.default(node, this.cfiBase, ignoreClass).toString();
}
// TODO: find where this is used - remove?
}, {
key: "map",
value: function map(layout) {
var map = new _mapping2.default(layout);
return map.section();
}
/**
* Size the contents to a given width and height
* @param {number} [width]
* @param {number} [height]
*/
}, {
key: "size",
value: function size(width, height) {
var viewport = { scale: 1.0, scalable: "no" };
this.layoutStyle("scrolling");
if (width >= 0) {
this.width(width);
viewport.width = width;
this.css("padding", "0 " + width / 12 + "px");
}
if (height >= 0) {
this.height(height);
viewport.height = height;
}
this.css("margin", "0");
this.css("box-sizing", "border-box");
this.viewport(viewport);
}
/**
* Apply columns to the contents for pagination
* @param {number} width
* @param {number} height
* @param {number} columnWidth
* @param {number} gap
*/
}, {
key: "columns",
value: function columns(width, height, columnWidth, gap, dir) {
var COLUMN_AXIS = (0, _core.prefixed)("column-axis");
var COLUMN_GAP = (0, _core.prefixed)("column-gap");
var COLUMN_WIDTH = (0, _core.prefixed)("column-width");
var COLUMN_FILL = (0, _core.prefixed)("column-fill");
var writingMode = this.writingMode();
var axis = writingMode.indexOf("vertical") === 0 ? "vertical" : "horizontal";
this.layoutStyle("paginated");
if (dir === "rtl" && axis === "horizontal") {
this.direction(dir);
}
this.width(width);
this.height(height);
// Deal with Mobile trying to scale to viewport
this.viewport({ width: width, height: height, scale: 1.0, scalable: "no" });
// TODO: inline-block needs more testing
// Fixes Safari column cut offs, but causes RTL issues
// this.css("display", "inline-block");
this.css("overflow-y", "hidden");
this.css("margin", "0", true);
if (axis === "vertical") {
this.css("padding-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");
// Fix glyph clipping in WebKit
// https://github.com/futurepress/epub.js/issues/983
this.css("-webkit-line-box-contain", "block glyphs replaced");
}
/**
* Scale contents from center
* @param {number} scale
* @param {number} offsetX
* @param {number} offsetY
*/
}, {
key: "scaler",
value: function scaler(scale, offsetX, offsetY) {
var scaleStr = "scale(" + scale + ")";
var translateStr = "";
// this.css("position", "absolute"));
this.css("transform-origin", "top left");
if (offsetX >= 0 || offsetY >= 0) {
translateStr = " translate(" + (offsetX || 0) + "px, " + (offsetY || 0) + "px )";
}
this.css("transform", scaleStr + translateStr);
}
/**
* Fit contents into a fixed width and height
* @param {number} width
* @param {number} height
*/
}, {
key: "fit",
value: function fit(width, height, 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 0 ? offsetX : 0, offsetY);
// background images are not scaled by transform
this.css("background-size", viewportWidth * scale + "px " + viewportHeight * scale + "px");
this.css("background-color", "transparent");
if (section && section.properties.includes("page-spread-left")) {
// set margin since scale is weird
var marginLeft = width - viewportWidth * scale;
this.css("margin-left", marginLeft + "px");
}
}
/**
* Set the direction of the text
* @param {string} [dir="ltr"] "rtl" | "ltr"
*/
}, {
key: "direction",
value: function direction(dir) {
if (this.documentElement) {
this.documentElement.style["direction"] = dir;
}
}
}, {
key: "mapPage",
value: function mapPage(cfiBase, layout, start, end, dev) {
var mapping = new _mapping2.default(layout, dev);
return mapping.page(this, cfiBase, start, end);
}
/**
* Emit event when link in content is clicked
* @private
*/
}, {
key: "linksHandler",
value: function linksHandler() {
var _this2 = this;
(0, _replacements.replaceLinks)(this.content, function (href) {
_this2.emit(_constants.EVENTS.CONTENTS.LINK_CLICKED, href);
});
}
/**
* Set the writingMode of the text
* @param {string} [mode="horizontal-tb"] "horizontal-tb" | "vertical-rl" | "vertical-lr"
*/
}, {
key: "writingMode",
value: function writingMode(mode) {
var WRITING_MODE = (0, _core.prefixed)("writing-mode");
if (mode && this.documentElement) {
this.documentElement.style[WRITING_MODE] = mode;
}
return this.window.getComputedStyle(this.documentElement)[WRITING_MODE] || '';
}
/**
* Set the layoutStyle of the content
* @param {string} [style="paginated"] "scrolling" | "paginated"
* @private
*/
}, {
key: "layoutStyle",
value: function layoutStyle(style) {
if (style) {
this._layoutStyle = style;
navigator.epubReadingSystem.layoutStyle = this._layoutStyle;
}
return this._layoutStyle || "paginated";
}
/**
* Add the epubReadingSystem object to the navigator
* @param {string} name
* @param {string} version
* @private
*/
}, {
key: "epubReadingSystem",
value: function epubReadingSystem(name, version) {
navigator.epubReadingSystem = {
name: name,
version: version,
layoutStyle: this.layoutStyle(),
hasFeature: function hasFeature(feature) {
switch (feature) {
case "dom-manipulation":
return true;
case "layout-changes":
return true;
case "touch-events":
return true;
case "mouse-events":
return true;
case "keyboard-events":
return true;
case "spine-scripting":
return false;
default:
return false;
}
}
};
return navigator.epubReadingSystem;
}
}, {
key: "destroy",
value: function destroy() {
// Stop observing
if (this.observer) {
this.observer.disconnect();
}
this.document.removeEventListener('transitionend', this._resizeCheck);
this.removeListeners();
}
}], [{
key: "listenedEvents",
get: function get() {
return _constants.DOM_EVENTS;
}
}]);
return Contents;
}();
(0, _eventEmitter2.default)(Contents.prototype);
exports.default = Contents;
module.exports = exports["default"];
/***/ }),
/* 15 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i 1) {
if (forceRight || section.index === 0) {
// First page (cover) should stand alone for pre-paginated books
return;
}
next = section.next();
if (next && !next.properties.includes("page-spread-left")) {
return action.call(this, next);
}
}
}
}, {
key: "display",
value: function display(section, target) {
var displaying = new _core.defer();
var displayed = displaying.promise;
// Check if moving to target is needed
if (target === section.href || (0, _core.isNumber)(target)) {
target = undefined;
}
// Check to make sure the section we want isn't already shown
var visible = this.views.find(section);
// View is already shown, just move to correct location in view
if (visible && section && this.layout.name !== "pre-paginated") {
var offset = visible.offset();
if (this.settings.direction === "ltr") {
this.scrollTo(offset.left, offset.top, true);
} else {
var width = visible.width();
this.scrollTo(offset.left + width, offset.top, true);
}
if (target) {
var _offset = visible.locationOf(target);
this.moveTo(_offset);
}
displaying.resolve();
return displayed;
}
// Hide all current views
this.clear();
var 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) {
// Move to correct place within the section, if needed
if (target) {
var _offset2 = view.locationOf(target);
this.moveTo(_offset2);
}
}.bind(this), function (err) {
displaying.reject(err);
}).then(function () {
return this.handleNextPrePaginated(forceRight, section, this.add);
}.bind(this)).then(function () {
this.views.show();
displaying.resolve();
}.bind(this));
// .then(function(){
// return this.hooks.display.trigger(view);
// }.bind(this))
// .then(function(){
// this.views.show();
// }.bind(this));
return displayed;
}
}, {
key: "afterDisplayed",
value: function afterDisplayed(view) {
this.emit(_constants.EVENTS.MANAGERS.ADDED, view);
}
}, {
key: "afterResized",
value: function afterResized(view) {
this.emit(_constants.EVENTS.MANAGERS.RESIZE, view.section);
}
}, {
key: "moveTo",
value: function moveTo(offset) {
var distX = 0,
distY = 0;
if (!this.isPaginated) {
distY = offset.top;
} else {
distX = Math.floor(offset.left / this.layout.delta) * this.layout.delta;
if (distX + this.layout.delta > this.container.scrollWidth) {
distX = this.container.scrollWidth - this.layout.delta;
}
}
this.scrollTo(distX, distY, true);
}
}, {
key: "add",
value: function add(section, forceRight) {
var _this = this;
var view = this.createView(section, forceRight);
this.views.append(view);
// view.on(EVENTS.VIEWS.SHOWN, this.afterDisplayed.bind(this));
view.onDisplayed = this.afterDisplayed.bind(this);
view.onResize = this.afterResized.bind(this);
view.on(_constants.EVENTS.VIEWS.AXIS, function (axis) {
_this.updateAxis(axis);
});
return view.display(this.request);
}
}, {
key: "append",
value: function append(section, forceRight) {
var _this2 = this;
var view = this.createView(section, forceRight);
this.views.append(view);
view.onDisplayed = this.afterDisplayed.bind(this);
view.onResize = this.afterResized.bind(this);
view.on(_constants.EVENTS.VIEWS.AXIS, function (axis) {
_this2.updateAxis(axis);
});
return view.display(this.request);
}
}, {
key: "prepend",
value: function prepend(section, forceRight) {
var _this3 = this;
var view = this.createView(section, forceRight);
view.on(_constants.EVENTS.VIEWS.RESIZED, function (bounds) {
_this3.counter(bounds);
});
this.views.prepend(view);
view.onDisplayed = this.afterDisplayed.bind(this);
view.onResize = this.afterResized.bind(this);
view.on(_constants.EVENTS.VIEWS.AXIS, function (axis) {
_this3.updateAxis(axis);
});
return view.display(this.request);
}
}, {
key: "counter",
value: function counter(bounds) {
if (this.settings.axis === "vertical") {
this.scrollBy(0, bounds.heightDelta, true);
} else {
this.scrollBy(bounds.widthDelta, 0, true);
}
}
// resizeView(view) {
//
// if(this.settings.globalLayoutProperties.layout === "pre-paginated") {
// view.lock("both", this.bounds.width, this.bounds.height);
// } else {
// view.lock("width", this.bounds.width, this.bounds.height);
// }
//
// };
}, {
key: "next",
value: function next() {
var next;
var left;
var dir = this.settings.direction;
if (!this.views.length) return;
if (this.isPaginated && this.settings.axis === "horizontal" && (!dir || dir === "ltr")) {
this.scrollLeft = this.container.scrollLeft;
left = this.container.scrollLeft + this.container.offsetWidth + this.layout.delta;
if (left 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;
var top = this.container.scrollTop + this.container.offsetHeight;
if (top 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 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();
var 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 left;
if (this.layout.name === "pre-paginated" && this.layout.divisor > 1) {
left = prev.prev();
if (left) {
return this.prepend(left);
}
}
}.bind(this), function (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));
}
}
}, {
key: "current",
value: function current() {
var visible = this.visible();
if (visible.length) {
// Current is the last visible view
return visible[visible.length - 1];
}
return null;
}
}, {
key: "clear",
value: function clear() {
// this.q.clear();
if (this.views) {
this.views.hide();
this.scrollTo(0, 0, true);
this.views.clear();
}
}
}, {
key: "currentLocation",
value: function currentLocation() {
if (this.settings.axis === "vertical") {
this.location = this.scrolledLocation();
} else {
this.location = this.paginatedLocation();
}
return this.location;
}
}, {
key: "scrolledLocation",
value: function scrolledLocation() {
var _this4 = this;
var visible = this.visible();
var container = this.container.getBoundingClientRect();
var pageHeight = container.height height) {
endPos = height;
used = endPos - startPos;
}
var totalPages = _this4.layout.count(height, pageHeight).pages;
var currPage = Math.ceil(startPos / pageHeight);
var pages = [];
var endPage = Math.ceil(endPos / pageHeight);
pages = [];
for (var i = currPage; i container.left - offsetPrev && position.left container.top - offsetPrev && position.top 0 && this.layout.name === "pre-paginated") {
this.display(this.views.first().section);
}
// this.manager.layout(this.layout.format);
}
}, {
key: "updateLayout",
value: function updateLayout() {
if (!this.stage) {
return;
}
this._stageSize = this.stage.size();
if (!this.isPaginated) {
this.layout.calculate(this._stageSize.width, this._stageSize.height);
} else {
this.layout.calculate(this._stageSize.width, this._stageSize.height, this.settings.gap);
// Set the look ahead offset for what is visible
this.settings.offset = this.layout.delta;
// this.stage.addStyleRules("iframe", [{"margin-right" : this.layout.gap + "px"}]);
}
// Set the dimensions for views
this.viewSettings.width = this.layout.width;
this.viewSettings.height = this.layout.height;
this.setLayout(this.layout);
}
}, {
key: "setLayout",
value: function setLayout(layout) {
this.viewSettings.layout = layout;
this.mapping = new _mapping2.default(layout.props, this.settings.direction, this.settings.axis);
if (this.views) {
this.views.forEach(function (view) {
if (view) {
view.setLayout(layout);
}
});
}
}
}, {
key: "updateAxis",
value: function updateAxis(axis, forceUpdate) {
if (!this.isPaginated) {
axis = "vertical";
}
if (!forceUpdate && axis === this.settings.axis) {
return;
}
this.settings.axis = axis;
this.stage && this.stage.axis(axis);
this.viewSettings.axis = axis;
if (this.mapping) {
this.mapping = new _mapping2.default(this.layout.props, this.settings.direction, this.settings.axis);
}
if (this.layout) {
if (axis === "vertical") {
this.layout.spread("none");
} else {
this.layout.spread(this.layout.settings.spread);
}
}
}
}, {
key: "updateFlow",
value: function updateFlow(flow) {
var defaultScrolledOverflow = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "auto";
var 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();
}
}, {
key: "getContents",
value: function getContents() {
var contents = [];
if (!this.views) {
return contents;
}
this.views.forEach(function (view) {
var viewContents = view && view.contents;
if (viewContents) {
contents.push(viewContents);
}
});
return contents;
}
}, {
key: "direction",
value: function direction() {
var dir = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "ltr";
this.settings.direction = dir;
this.stage && this.stage.direction(dir);
this.viewSettings.direction = dir;
this.updateLayout();
}
}, {
key: "isRendered",
value: function isRendered() {
return this.rendered;
}
}]);
return DefaultViewManager;
}();
//-- Enable binding events to Manager
(0, _eventEmitter2.default)(DefaultViewManager.prototype);
exports.default = DefaultViewManager;
module.exports = exports["default"];
/***/ }),
/* 16 */
/***/ (function(module, exports) {
/**
* Checks if `value` is the
* [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
* of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an object, else `false`.
* @example
*
* _.isObject({});
* // => true
*
* _.isObject([1, 2, 3]);
* // => true
*
* _.isObject(_.noop);
* // => true
*
* _.isObject(null);
* // => false
*/
function isObject(value) {
var type = typeof value;
return value != null && (type == 'object' || type == 'function');
}
module.exports = isObject;
/***/ }),
/* 17 */
/***/ (function(module, exports) {
/*
* DOM Level 2
* Object DOMException
* @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
* @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
*/
function copy(src,dest){
for(var p in src){
dest[p] = src[p];
}
}
/**
^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));?
^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));?
*/
function _extends(Class,Super){
var pt = Class.prototype;
if(Object.create){
var ppt = Object.create(Super.prototype)
pt.__proto__ = ppt;
}
if(!(pt instanceof Super)){
function t(){};
t.prototype = Super.prototype;
t = new t();
copy(pt,t);
Class.prototype = pt = t;
}
if(pt.constructor != Class){
if(typeof Class != 'function'){
console.error("unknow Class:"+Class)
}
pt.constructor = Class
}
}
var htmlns = 'http://www.w3.org/1999/xhtml' ;
// Node Types
var NodeType = {}
var ELEMENT_NODE = NodeType.ELEMENT_NODE = 1;
var ATTRIBUTE_NODE = NodeType.ATTRIBUTE_NODE = 2;
var TEXT_NODE = 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 = 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;
// ExceptionCode
var ExceptionCode = {}
var ExceptionMessage = {};
var INDEX_SIZE_ERR = ExceptionCode.INDEX_SIZE_ERR = ((ExceptionMessage[1]="Index size error"),1);
var DOMSTRING_SIZE_ERR = ExceptionCode.DOMSTRING_SIZE_ERR = ((ExceptionMessage[2]="DOMString size error"),2);
var HIERARCHY_REQUEST_ERR = ExceptionCode.HIERARCHY_REQUEST_ERR = ((ExceptionMessage[3]="Hierarchy request error"),3);
var WRONG_DOCUMENT_ERR = ExceptionCode.WRONG_DOCUMENT_ERR = ((ExceptionMessage[4]="Wrong document"),4);
var INVALID_CHARACTER_ERR = ExceptionCode.INVALID_CHARACTER_ERR = ((ExceptionMessage[5]="Invalid character"),5);
var NO_DATA_ALLOWED_ERR = ExceptionCode.NO_DATA_ALLOWED_ERR = ((ExceptionMessage[6]="No data allowed"),6);
var NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = ((ExceptionMessage[7]="No modification allowed"),7);
var NOT_FOUND_ERR = ExceptionCode.NOT_FOUND_ERR = ((ExceptionMessage[8]="Not found"),8);
var NOT_SUPPORTED_ERR = ExceptionCode.NOT_SUPPORTED_ERR = ((ExceptionMessage[9]="Not supported"),9);
var INUSE_ATTRIBUTE_ERR = ExceptionCode.INUSE_ATTRIBUTE_ERR = ((ExceptionMessage[10]="Attribute in use"),10);
//level2
var INVALID_STATE_ERR = ExceptionCode.INVALID_STATE_ERR = ((ExceptionMessage[11]="Invalid state"),11);
var SYNTAX_ERR = ExceptionCode.SYNTAX_ERR = ((ExceptionMessage[12]="Syntax error"),12);
var INVALID_MODIFICATION_ERR = ExceptionCode.INVALID_MODIFICATION_ERR = ((ExceptionMessage[13]="Invalid modification"),13);
var NAMESPACE_ERR = ExceptionCode.NAMESPACE_ERR = ((ExceptionMessage[14]="Invalid namespace"),14);
var INVALID_ACCESS_ERR = 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)
/**
* @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177
* The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live.
* The items in the NodeList are accessible via an integral index, starting from 0.
*/
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 this[index] || null;
},
toString:function(isHTML,nodeFilter){
for(var buf = [], i = 0;i=0){
var lastIndex = list.length-1
while(i0 || key == 'xmlns'){
// return null;
// }
//console.log()
var i = this.length;
while(i--){
var attr = this[i];
//console.log(attr.nodeName,key)
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) {// raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR
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;
}
};
/**
* @see http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490
*/
function DOMImplementation(/* Object */ features) {
this._features = {};
if (features) {
for (var feature in features) {
this._features = features[feature];
}
}
};
DOMImplementation.prototype = {
hasFeature: function(/* string */ feature, /* string */ version) {
var versions = this._features[feature.toLowerCase()];
if (versions && (!version || version in versions)) {
return true;
} else {
return false;
}
},
// Introduced in DOM Level 2:
createDocument:function(namespaceURI, qualifiedName, doctype){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR,WRONG_DOCUMENT_ERR
var doc = new Document();
doc.implementation = this;
doc.childNodes = new NodeList();
doc.doctype = doctype;
if(doctype){
doc.appendChild(doctype);
}
if(qualifiedName){
var root = doc.createElementNS(namespaceURI,qualifiedName);
doc.appendChild(root);
}
return doc;
},
// Introduced in DOM Level 2:
createDocumentType:function(qualifiedName, publicId, systemId){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR
var node = new DocumentType();
node.name = qualifiedName;
node.nodeName = qualifiedName;
node.publicId = publicId;
node.systemId = systemId;
// Introduced in DOM Level 2:
//readonly attribute DOMString internalSubset;
//TODO:..
// readonly attribute NamedNodeMap entities;
// readonly attribute NamedNodeMap notations;
return node;
}
};
/**
* @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247
*/
function Node() {
};
Node.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){//raises
return _insertBefore(this,newChild,refChild);
},
replaceChild:function(newChild, oldChild){//raises
this.insertBefore(newChild,oldChild);
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 && child.nodeType == TEXT_NODE){
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;
},
lookupPrefix:function(namespaceURI){
var el = this;
while(el){
var map = el._nsMap;
//console.dir(map)
if(map){
for(var n in map){
if(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;
//console.dir(map)
if(map){
if(prefix in map){
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 == '' && '>' ||
c == '&' && '&' ||
c == '"' && '"' ||
''+c.charCodeAt()+';'
}
copy(NodeType,Node);
copy(NodeType,Node.prototype);
/**
* @param callback return true for continue,false for break
* @return boolean true: break visit;
*/
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(){
}
function _onAddAttribute(doc,el,newAttr){
doc && doc._inc++;
var ns = newAttr.namespaceURI ;
if(ns == 'http://www.w3.org/2000/xmlns/'){
//update namespace
el._nsMap[newAttr.prefix?newAttr.localName:''] = newAttr.value
}
}
function _onRemoveAttribute(doc,el,newAttr,remove){
doc && doc._inc++;
var ns = newAttr.namespaceURI ;
if(ns == 'http://www.w3.org/2000/xmlns/'){
//update namespace
delete el._nsMap[newAttr.prefix?newAttr.localName:'']
}
}
function _onUpdateChild(doc,el,newChild){
if(doc && doc._inc){
doc._inc++;
//update childNodes
var cs = el.childNodes;
if(newChild){
cs[cs.length++] = newChild;
}else{
//console.log(1)
var child = el.firstChild;
var i = 0;
while(child){
cs[i++] = child;
child =child.nextSibling;
}
cs.length = i;
}
}
}
/**
* attributes;
* children;
*
* writeable properties:
* nodeValue,Attr:value,CharacterData:data
* prefix
*/
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;
}
_onUpdateChild(parentNode.ownerDocument,parentNode);
return child;
}
/**
* preformance key(refChild == null)
*/
function _insertBefore(parentNode,newChild,nextChild){
var cp = newChild.parentNode;
if(cp){
cp.removeChild(newChild);//remove and update
}
if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
var newFirst = newChild.firstChild;
if (newFirst == null) {
return newChild;
}
var newLast = newChild.lastChild;
}else{
newFirst = newLast = newChild;
}
var pre = nextChild ? nextChild.previousSibling : parentNode.lastChild;
newFirst.previousSibling = pre;
newLast.nextSibling = nextChild;
if(pre){
pre.nextSibling = newFirst;
}else{
parentNode.firstChild = newFirst;
}
if(nextChild == null){
parentNode.lastChild = newLast;
}else{
nextChild.previousSibling = newLast;
}
do{
newFirst.parentNode = parentNode;
}while(newFirst !== newLast && (newFirst= newFirst.nextSibling))
_onUpdateChild(parentNode.ownerDocument||parentNode,parentNode);
//console.log(parentNode.lastChild.nextSibling == null)
if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) {
newChild.firstChild = newChild.lastChild = null;
}
return newChild;
}
function _appendSingleChild(parentNode,newChild){
var cp = newChild.parentNode;
if(cp){
var pre = parentNode.lastChild;
cp.removeChild(newChild);//remove and update
var pre = parentNode.lastChild;
}
var pre = parentNode.lastChild;
newChild.parentNode = parentNode;
newChild.previousSibling = pre;
newChild.nextSibling = null;
if(pre){
pre.nextSibling = newChild;
}else{
parentNode.firstChild = newChild;
}
parentNode.lastChild = newChild;
_onUpdateChild(parentNode.ownerDocument,parentNode,newChild);
return newChild;
//console.log("__aa",parentNode.lastChild.nextSibling == null)
}
Document.prototype = {
//implementation : null,
nodeName : '#document',
nodeType : DOCUMENT_NODE,
doctype : null,
documentElement : null,
_inc : 1,
insertBefore : function(newChild, refChild){//raises
if(newChild.nodeType == DOCUMENT_FRAGMENT_NODE){
var child = newChild.firstChild;
while(child){
var next = child.nextSibling;
this.insertBefore(child,refChild);
child = next;
}
return newChild;
}
if(this.documentElement == null && newChild.nodeType == ELEMENT_NODE){
this.documentElement = newChild;
}
return _insertBefore(this,newChild,refChild),(newChild.ownerDocument = this),newChild;
},
removeChild : function(oldChild){
if(this.documentElement == oldChild){
this.documentElement = null;
}
return _removeChild(this,oldChild);
},
// 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){
if(node.getAttribute('id') == id){
rtv = node;
return true;
}
}
})
return rtv;
},
//document factory method:
createElement : function(tagName){
var node = new Element();
node.ownerDocument = this;
node.nodeName = tagName;
node.tagName = 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.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();
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{
//el.prefix = null;
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{
//el.prefix = null;
node.localName = qualifiedName;
}
return node;
}
};
_extends(Document,Node);
function Element() {
this._nsMap = {};
};
Element.prototype = {
nodeType : ELEMENT_NODE,
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){
//console.log(this == oldAttr.ownerElement)
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 && (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 && (namespaceURI === '*' || node.namespaceURI === namespaceURI) && (localName === '*' || node.localName == localName)){
ls.push(node);
}
});
return ls;
});
}
};
Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName;
Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS;
_extends(Element,Node);
function Attr() {
};
Attr.prototype.nodeType = ATTRIBUTE_NODE;
_extends(Attr,Node);
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);
function Text() {
};
Text.prototype = {
nodeName : "#text",
nodeType : TEXT_NODE,
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);
function Notation() {
};
Notation.prototype.nodeType = NOTATION_NODE;
_extends(Notation,Node);
function Entity() {
};
Entity.prototype.nodeType = ENTITY_NODE;
_extends(Entity,Node);
function EntityReference() {
};
EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;
_extends(EntityReference,Node);
function DocumentFragment() {
};
DocumentFragment.prototype.nodeName = "#document-fragment";
DocumentFragment.prototype.nodeType = DOCUMENT_FRAGMENT_NODE;
_extends(DocumentFragment,Node);
function ProcessingInstruction() {
}
ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;
_extends(ProcessingInstruction,Node);
function XMLSerializer(){}
XMLSerializer.prototype.serializeToString = function(node,isHtml,nodeFilter){
return nodeSerializeToString.call(node,isHtml,nodeFilter);
}
Node.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){
//console.log(prefix)
var prefix = refNode.lookupPrefix(uri);
if(prefix == null){
//isHTML = true;
var visibleNamespaces=[
{namespace:uri,prefix:null}
//{namespace:uri,prefix:''}
]
}
}
serializeToString(this,buf,isHtml,nodeFilter,visibleNamespaces);
//console.log('###',this.nodeType,uri,prefix,buf.join(''))
return buf.join('');
}
function needNamespaceDefine(node,isHTML, visibleNamespaces) {
var prefix = node.prefix||'';
var uri = node.namespaceURI;
if (!prefix && !uri){
return false;
}
if (prefix === "xml" && uri === "http://www.w3.org/XML/1998/namespace"
|| uri == 'http://www.w3.org/2000/xmlns/'){
return false;
}
var i = visibleNamespaces.length
//console.log('@@@@',node.tagName,prefix,uri,visibleNamespaces)
while (i--) {
var ns = visibleNamespaces[i];
// get namespace prefix
//console.log(node.nodeType,node.tagName,ns.prefix,prefix)
if (ns.prefix == prefix){
return ns.namespace != uri;
}
}
//console.log(isHTML,uri,prefix=='')
//if(isHTML && prefix ==null && uri == 'http://www.w3.org/1999/xhtml'){
// return false;
//}
//node.flag = '11111'
//console.error(3,true,node.flag,node.prefix,node.namespaceURI)
return true;
}
function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){
if(nodeFilter){
node = nodeFilter(node);
if(node){
if(typeof node == 'string'){
buf.push(node);
return;
}
}else{
return;
}
//buf.sort.apply(attrs, attributeSorter);
}
switch(node.nodeType){
case ELEMENT_NODE:
if (!visibleNamespaces) visibleNamespaces = [];
var startVisibleNamespaces = visibleNamespaces.length;
var attrs = node.attributes;
var len = attrs.length;
var child = node.firstChild;
var nodeName = node.tagName;
isHTML = (htmlns === node.namespaceURI) ||isHTML
buf.push('');
//if is cdata child node
if(isHTML && /^script$/i.test(nodeName)){
while(child){
if(child.data){
buf.push(child.data);
}else{
serializeToString(child,buf,isHTML,nodeFilter,visibleNamespaces);
}
child = child.nextSibling;
}
}else
{
while(child){
serializeToString(child,buf,isHTML,nodeFilter,visibleNamespaces);
child = child.nextSibling;
}
}
buf.push('',nodeName,'>');
}else{
buf.push('/>');
}
// remove added visible namespaces
//visibleNamespaces.length = startVisibleNamespaces;
return;
case DOCUMENT_NODE:
case DOCUMENT_FRAGMENT_NODE:
var child = node.firstChild;
while(child){
serializeToString(child,buf,isHTML,nodeFilter,visibleNamespaces);
child = child.nextSibling;
}
return;
case ATTRIBUTE_NODE:
return buf.push(' ',node.name,'="',node.value.replace(/[');
case COMMENT_NODE:
return buf.push( "");
case DOCUMENT_TYPE_NODE:
var pubid = node.publicId;
var sysid = node.systemId;
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,';');
//case ENTITY_NODE:
//case NOTATION_NODE:
default:
buf.push('??',node.nodeName);
}
}
function importNode(doc,node,deep){
var node2;
switch (node.nodeType) {
case ELEMENT_NODE:
node2 = node.cloneNode(false);
node2.ownerDocument = doc;
//var attrs = node2.attributes;
//var len = attrs.length;
//for(var i=0;i 0) && (this.settings.height === 0 || this.settings.height > 0)) {
// viewport = "width="+this.settings.width+", height="+this.settings.height+"";
}
properties = {
layout: layout,
spread: spread,
orientation: orientation,
flow: flow,
viewport: viewport,
minSpreadWidth: minSpreadWidth,
direction: direction
};
return properties;
}
/**
* Adjust the flow of the rendition to paginated or scrolled
* (scrolled-continuous vs scrolled-doc are handled by different view managers)
* @param {string} flow
*/
}, {
key: "flow",
value: function flow(_flow2) {
var _flow = _flow2;
if (_flow2 === "scrolled" || _flow2 === "scrolled-doc" || _flow2 === "scrolled-continuous") {
_flow = "scrolled";
}
if (_flow2 === "auto" || _flow2 === "paginated") {
_flow = "paginated";
}
this.settings.flow = _flow2;
if (this._layout) {
this._layout.flow(_flow);
}
if (this.manager && this._layout) {
this.manager.applyLayout(this._layout);
}
if (this.manager) {
this.manager.updateFlow(_flow);
}
if (this.manager && this.manager.isRendered() && this.location) {
this.manager.clear();
this.display(this.location.start.cfi);
}
}
/**
* Adjust the layout of the rendition to reflowable or pre-paginated
* @param {object} settings
*/
}, {
key: "layout",
value: function layout(settings) {
var _this4 = this;
if (settings) {
this._layout = new _layout2.default(settings);
this._layout.spread(settings.spread, this.settings.minSpreadWidth);
// this.mapping = new Mapping(this._layout.props);
this._layout.on(_constants.EVENTS.LAYOUT.UPDATED, function (props, changed) {
_this4.emit(_constants.EVENTS.RENDITION.LAYOUT, props, changed);
});
}
if (this.manager && this._layout) {
this.manager.applyLayout(this._layout);
}
return this._layout;
}
/**
* Adjust if the rendition uses spreads
* @param {string} spread none | auto (TODO: implement landscape, portrait, both)
* @param {int} [min] min width to use spreads at
*/
}, {
key: "spread",
value: function spread(_spread, min) {
this.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
*/
}, {
key: "direction",
value: function direction(dir) {
this.settings.direction = dir || "ltr";
if (this.manager) {
this.manager.direction(this.settings.direction);
}
if (this.manager && this.manager.isRendered() && this.location) {
this.manager.clear();
this.display(this.location.start.cfi);
}
}
/**
* Report the current location
* @fires relocated
* @fires locationChanged
*/
}, {
key: "reportLocation",
value: function reportLocation() {
return this.q.enqueue(function reportedLocation() {
requestAnimationFrame(function reportedLocationAfterRAF() {
var location = this.manager.currentLocation();
if (location && location.then && typeof location.then === "function") {
location.then(function (result) {
var located = this.located(result);
if (!located || !located.start || !located.end) {
return;
}
this.location = located;
this.emit(_constants.EVENTS.RENDITION.LOCATION_CHANGED, {
index: this.location.start.index,
href: this.location.start.href,
start: this.location.start.cfi,
end: this.location.end.cfi,
percentage: this.location.start.percentage
});
this.emit(_constants.EVENTS.RENDITION.RELOCATED, this.location);
}.bind(this));
} else if (location) {
var located = this.located(location);
if (!located || !located.start || !located.end) {
return;
}
this.location = located;
/**
* @event locationChanged
* @deprecated
* @type {object}
* @property {number} index
* @property {string} href
* @property {EpubCFI} start
* @property {EpubCFI} end
* @property {number} percentage
* @memberof Rendition
*/
this.emit(_constants.EVENTS.RENDITION.LOCATION_CHANGED, {
index: this.location.start.index,
href: this.location.start.href,
start: this.location.start.cfi,
end: this.location.end.cfi,
percentage: this.location.start.percentage
});
/**
* @event relocated
* @type {displayedLocation}
* @memberof Rendition
*/
this.emit(_constants.EVENTS.RENDITION.RELOCATED, this.location);
}
}.bind(this));
}.bind(this));
}
/**
* Get the Current Location object
* @return {displayedLocation | promise} location (may be a promise)
*/
}, {
key: "currentLocation",
value: function currentLocation() {
var location = this.manager.currentLocation();
if (location && location.then && typeof location.then === "function") {
location.then(function (result) {
var located = this.located(result);
return located;
}.bind(this));
} else if (location) {
var located = this.located(location);
return located;
}
}
/**
* Creates a Rendition#locationRange from location
* passed by the Manager
* @returns {displayedLocation}
* @private
*/
}, {
key: "located",
value: function located(location) {
if (!location.length) {
return {};
}
var start = location[0];
var end = location[location.length - 1];
var located = {
start: {
index: start.index,
href: start.href,
cfi: start.mapping.start,
displayed: {
page: start.pages[0] || 1,
total: start.totalPages
}
},
end: {
index: end.index,
href: end.href,
cfi: end.mapping.end,
displayed: {
page: end.pages[end.pages.length - 1] || 1,
total: end.totalPages
}
}
};
var locationStart = this.book.locations.locationFromCfi(start.mapping.start);
var locationEnd = this.book.locations.locationFromCfi(end.mapping.end);
if (locationStart != null) {
located.start.location = locationStart;
located.start.percentage = this.book.locations.percentageFromLocation(locationStart);
}
if (locationEnd != null) {
located.end.location = locationEnd;
located.end.percentage = this.book.locations.percentageFromLocation(locationEnd);
}
var pageStart = this.book.pageList.pageFromCfi(start.mapping.start);
var pageEnd = this.book.pageList.pageFromCfi(end.mapping.end);
if (pageStart != -1) {
located.start.page = pageStart;
}
if (pageEnd != -1) {
located.end.page = pageEnd;
}
if (end.index === this.book.spine.last().index && located.end.displayed.page >= located.end.displayed.total) {
located.atEnd = true;
}
if (start.index === this.book.spine.first().index && located.start.displayed.page === 1) {
located.atStart = true;
}
return located;
}
/**
* Remove and Clean Up the Rendition
*/
}, {
key: "destroy",
value: function destroy() {
// Clear the queue
// this.q.clear();
// this.q = undefined;
this.manager && this.manager.destroy();
this.book = undefined;
// this.views = null;
// this.hooks.display.clear();
// this.hooks.serialize.clear();
// this.hooks.content.clear();
// this.hooks.layout.clear();
// this.hooks.render.clear();
// this.hooks.show.clear();
// this.hooks = {};
// this.themes.destroy();
// this.themes = undefined;
// this.epubcfi = undefined;
// this.starting = undefined;
// this.started = undefined;
}
/**
* Pass the events from a view's Contents
* @private
* @param {Contents} view contents
*/
}, {
key: "passEvents",
value: function passEvents(contents) {
var _this5 = this;
_constants.DOM_EVENTS.forEach(function (e) {
contents.on(e, function (ev) {
return _this5.triggerViewEvent(ev, contents);
});
});
contents.on(_constants.EVENTS.CONTENTS.SELECTED, function (e) {
return _this5.triggerSelectedEvent(e, contents);
});
}
/**
* Emit events passed by a view
* @private
* @param {event} e
*/
}, {
key: "triggerViewEvent",
value: function triggerViewEvent(e, contents) {
this.emit(e.type, e, contents);
}
/**
* Emit a selection event's CFI Range passed from a a view
* @private
* @param {EpubCFI} cfirange
*/
}, {
key: "triggerSelectedEvent",
value: function triggerSelectedEvent(cfirange, contents) {
/**
* Emit that a text selection has occured
* @event selected
* @param {EpubCFI} cfirange
* @param {Contents} contents
* @memberof Rendition
*/
this.emit(_constants.EVENTS.RENDITION.SELECTED, cfirange, contents);
}
/**
* Emit a markClicked event with the cfiRange and data from a mark
* @private
* @param {EpubCFI} cfirange
*/
}, {
key: "triggerMarkEvent",
value: function triggerMarkEvent(cfiRange, data, contents) {
/**
* Emit that a mark was clicked
* @event markClicked
* @param {EpubCFI} cfirange
* @param {object} data
* @param {Contents} contents
* @memberof Rendition
*/
this.emit(_constants.EVENTS.RENDITION.MARK_CLICKED, cfiRange, data, contents);
}
/**
* Get a Range from a Visible CFI
* @param {string} cfi EpubCfi String
* @param {string} ignoreClass
* @return {range}
*/
}, {
key: "getRange",
value: function getRange(cfi, ignoreClass) {
var _cfi = new _epubcfi2.default(cfi);
var found = this.manager.visible().filter(function (view) {
if (_cfi.spinePos === view.index) return true;
});
// Should only every return 1 item
if (found.length) {
return found[0].contents.range(_cfi, ignoreClass);
}
}
/**
* Hook to adjust images to fit in columns
* @param {Contents} contents
* @private
*/
}, {
key: "adjustImages",
value: function adjustImages(contents) {
if (this._layout.name === "pre-paginated") {
return new Promise(function (resolve) {
resolve();
});
}
var computed = contents.window.getComputedStyle(contents.content, null);
var height = (contents.content.offsetHeight - (parseFloat(computed.paddingTop) + parseFloat(computed.paddingBottom))) * .95;
var 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) {
// Wait to apply
setTimeout(function () {
resolve();
}, 1);
});
}
/**
* Get the Contents object of each rendered view
* @returns {Contents[]}
*/
}, {
key: "getContents",
value: function getContents() {
return this.manager ? this.manager.getContents() : [];
}
/**
* Get the views member from the manager
* @returns {Views}
*/
}, {
key: "views",
value: function views() {
var views = this.manager ? this.manager.views : undefined;
return views || [];
}
/**
* Hook to handle link clicks in rendered content
* @param {Contents} contents
* @private
*/
}, {
key: "handleLinks",
value: function handleLinks(contents) {
var _this6 = this;
if (contents) {
contents.on(_constants.EVENTS.CONTENTS.LINK_CLICKED, function (href) {
var relative = _this6.book.path.relative(href);
_this6.display(relative);
});
}
}
/**
* Hook to handle injecting stylesheet before
* a Section is serialized
* @param {document} doc
* @param {Section} section
* @private
*/
}, {
key: "injectStylesheet",
value: function injectStylesheet(doc, section) {
var style = doc.createElement("link");
style.setAttribute("type", "text/css");
style.setAttribute("rel", "stylesheet");
style.setAttribute("href", this.settings.stylesheet);
doc.getElementsByTagName("head")[0].appendChild(style);
}
/**
* Hook to handle injecting scripts before
* a Section is serialized
* @param {document} doc
* @param {Section} section
* @private
*/
}, {
key: "injectScript",
value: function injectScript(doc, section) {
var script = doc.createElement("script");
script.setAttribute("type", "text/javascript");
script.setAttribute("src", this.settings.script);
script.textContent = " "; // Needed to prevent self closing tag
doc.getElementsByTagName("head")[0].appendChild(script);
}
/**
* Hook to handle the document identifier before
* a Section is serialized
* @param {document} doc
* @param {Section} section
* @private
*/
}, {
key: "injectIdentifier",
value: function injectIdentifier(doc, section) {
var ident = this.book.packaging.metadata.identifier;
var meta = doc.createElement("meta");
meta.setAttribute("name", "dc.relation.ispartof");
if (ident) {
meta.setAttribute("content", ident);
}
doc.getElementsByTagName("head")[0].appendChild(meta);
}
}]);
return Rendition;
}();
//-- Enable binding events to Renderer
(0, _eventEmitter2.default)(Rendition.prototype);
exports.default = Rendition;
module.exports = exports["default"];
/***/ }),
/* 19 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i 0) {
return NodeFilter.FILTER_ACCEPT;
} else {
return NodeFilter.FILTER_REJECT;
}
}
};
var safeFilter = filter.acceptNode;
safeFilter.acceptNode = filter.acceptNode;
var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, safeFilter, false);
var node;
var result;
while (node = treeWalker.nextNode()) {
result = func(node);
if (result) break;
}
return result;
}
}, {
key: "findRanges",
value: function findRanges(view) {
var columns = [];
var scrollWidth = view.contents.scrollWidth();
var spreads = Math.ceil(scrollWidth / this.layout.spreadWidth);
var count = spreads * this.layout.divisor;
var columnWidth = this.layout.columnWidth;
var gap = this.layout.gap;
var start, end;
for (var i = 0; i = start && left start) {
return node;
} else {
$prev = node;
stack.push(node);
}
} else if (_this.horizontal && _this.direction === "rtl") {
left = elPos.left;
right = elPos.right;
if (right = start) {
return node;
} else if (left = start && top start) {
return node;
} else {
$prev = node;
stack.push(node);
}
}
});
if (found) {
return this.findTextStartRange(found, start, end);
}
}
// Return last element
return this.findTextStartRange($prev, start, end);
}
/**
* 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}
*/
}, {
key: "findEnd",
value: function findEnd(root, start, end) {
var _this2 = this;
var stack = [root];
var $el;
var $prev = root;
var found;
while (stack.length) {
$el = stack.shift();
found = this.walk($el, function (node) {
var left, right, top, bottom;
var elPos;
var elRange;
elPos = (0, _core.nodeBounds)(node);
if (_this2.horizontal && _this2.direction === "ltr") {
left = Math.round(elPos.left);
right = Math.round(elPos.right);
if (left > end && $prev) {
return $prev;
} else if (right > end) {
return node;
} else {
$prev = node;
stack.push(node);
}
} else if (_this2.horizontal && _this2.direction === "rtl") {
left = Math.round(_this2.horizontal ? elPos.left : elPos.top);
right = Math.round(_this2.horizontal ? elPos.right : elPos.bottom);
if (right end && $prev) {
return $prev;
} else if (bottom > end) {
return node;
} else {
$prev = node;
stack.push(node);
}
}
});
if (found) {
return this.findTextEndRange(found, start, end);
}
}
// end of chapter
return this.findTextEndRange($prev, start, end);
}
/**
* 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}
*/
}, {
key: "findTextStartRange",
value: function findTextStartRange(node, start, end) {
var ranges = this.splitTextNodeIntoRanges(node);
var range;
var pos;
var left, top, right;
for (var i = 0; i = start) {
return range;
}
} else if (this.horizontal && this.direction === "rtl") {
right = pos.right;
if (right = start) {
return range;
}
}
// prev = 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}
*/
}, {
key: "findTextEndRange",
value: function findTextEndRange(node, start, end) {
var ranges = this.splitTextNodeIntoRanges(node);
var prev;
var range;
var pos;
var left, right, top, bottom;
for (var i = 0; i 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 end && prev) {
return prev;
} else if (bottom > end) {
return range;
}
}
prev = range;
}
// Ends before limit
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[]}
*/
}, {
key: "splitTextNodeIntoRanges",
value: function splitTextNodeIntoRanges(node, _splitter) {
var ranges = [];
var textContent = node.textContent || "";
var text = textContent.trim();
var range;
var doc = node.ownerDocument;
var splitter = _splitter || " ";
var pos = text.indexOf(splitter);
if (pos === -1 || node.nodeType != Node.TEXT_NODE) {
range = doc.createRange();
range.selectNodeContents(node);
return [range];
}
range = doc.createRange();
range.setStart(node, 0);
range.setEnd(node, pos);
ranges.push(range);
range = false;
while (pos != -1) {
pos = text.indexOf(splitter, pos + 1);
if (pos > 0) {
if (range) {
range.setEnd(node, pos);
ranges.push(range);
}
range = doc.createRange();
range.setStart(node, pos + 1);
}
}
if (range) {
range.setEnd(node, text.length);
ranges.push(range);
}
return ranges;
}
/**
* 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(...)" }
*/
}, {
key: "rangePairToCfiPair",
value: function rangePairToCfiPair(cfiBase, rangePair) {
var startRange = rangePair.start;
var endRange = rangePair.end;
startRange.collapse(true);
endRange.collapse(false);
var startCfi = new _epubcfi2.default(startRange, cfiBase).toString();
var endCfi = new _epubcfi2.default(endRange, cfiBase).toString();
return {
start: startCfi,
end: endCfi
};
}
}, {
key: "rangeListToCfiList",
value: function rangeListToCfiList(cfiBase, columns) {
var map = [];
var cifPair;
for (var i = 0; i 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) {
// add a blank page
width += this.layout.pageWidth;
}
}
} // Expand Vertically
else if (this.settings.axis === "vertical") {
height = this.contents.textHeight();
}
// Only Resize if dimensions have changed or
// if Frame is still hidden, so needs reframing
if (this._needsReframe || width != this._width || height != this._height) {
this.reframe(width, height);
}
this._expanding = false;
}
}, {
key: "reframe",
value: function reframe(width, height) {
var _this2 = this;
var size;
if ((0, _core.isNumber)(width)) {
this.element.style.width = width + "px";
this.iframe.style.width = width + "px";
this._width = width;
}
if ((0, _core.isNumber)(height)) {
this.element.style.height = height + "px";
this.iframe.style.height = height + "px";
this._height = height;
}
var widthDelta = this.prevBounds ? width - this.prevBounds.width : width;
var heightDelta = this.prevBounds ? height - this.prevBounds.height : height;
size = {
width: width,
height: height,
widthDelta: widthDelta,
heightDelta: heightDelta
};
this.pane && this.pane.render();
requestAnimationFrame(function () {
var mark = void 0;
for (var m in _this2.marks) {
if (_this2.marks.hasOwnProperty(m)) {
mark = _this2.marks[m];
_this2.placeMark(mark.element, mark.range);
}
}
});
this.onResize(this, size);
this.emit(_constants.EVENTS.VIEWS.RESIZED, size);
this.prevBounds = size;
this.elementBounds = (0, _core.bounds)(this.element);
}
}, {
key: "load",
value: function load(contents) {
var loading = new _core.defer();
var loaded = loading.promise;
if (!this.iframe) {
loading.reject(new Error("No Iframe Available"));
return loaded;
}
this.iframe.onload = function (event) {
this.onLoad(event, loading);
}.bind(this);
if (this.settings.method === "blobUrl") {
this.blobUrl = (0, _core.createBlobUrl)(contents, "application/xhtml+xml");
this.iframe.src = this.blobUrl;
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();
// For Cordova windows platform
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;
}
}, {
key: "onLoad",
value: function onLoad(event, promise) {
var _this3 = this;
this.window = this.iframe.contentWindow;
this.document = this.iframe.contentDocument;
this.contents = new _contents2.default(this.document, this.document.body, this.section.cfiBase, this.section.index);
this.rendering = false;
var link = this.document.querySelector("link[rel='canonical']");
if (link) {
link.setAttribute("href", this.section.canonical);
} else {
link = this.document.createElement("link");
link.setAttribute("rel", "canonical");
link.setAttribute("href", this.section.canonical);
this.document.querySelector("head").appendChild(link);
}
this.contents.on(_constants.EVENTS.CONTENTS.EXPAND, function () {
if (_this3.displayed && _this3.iframe) {
_this3.expand();
if (_this3.contents) {
_this3.layout.format(_this3.contents);
}
}
});
this.contents.on(_constants.EVENTS.CONTENTS.RESIZE, function (e) {
if (_this3.displayed && _this3.iframe) {
_this3.expand();
if (_this3.contents) {
_this3.layout.format(_this3.contents);
}
}
});
promise.resolve(this.contents);
}
}, {
key: "setLayout",
value: function setLayout(layout) {
this.layout = layout;
if (this.contents) {
this.layout.format(this.contents);
this.expand();
}
}
}, {
key: "setAxis",
value: function setAxis(axis) {
// Force vertical for scrolled
if (this.layout.props.flow === "scrolled") {
axis = "vertical";
}
this.settings.axis = axis;
if (axis == "horizontal") {
this.element.style.flex = "none";
} else {
this.element.style.flex = "initial";
}
this.size();
}
}, {
key: "addListeners",
value: function addListeners() {
//TODO: Add content listeners for expanding
}
}, {
key: "removeListeners",
value: function removeListeners(layoutFunc) {
//TODO: remove content listeners for expanding
}
}, {
key: "display",
value: function display(request) {
var displayed = new _core.defer();
if (!this.displayed) {
this.render(request).then(function () {
this.emit(_constants.EVENTS.VIEWS.DISPLAYED, this);
this.onDisplayed(this);
this.displayed = true;
displayed.resolve(this);
}.bind(this), function (err) {
displayed.reject(err, this);
});
} else {
displayed.resolve(this);
}
return displayed.promise;
}
}, {
key: "show",
value: function show() {
this.element.style.visibility = "visible";
if (this.iframe) {
this.iframe.style.visibility = "visible";
// Remind Safari to redraw the iframe
this.iframe.style.transform = "translateZ(0)";
this.iframe.offsetWidth;
this.iframe.style.transform = null;
}
this.emit(_constants.EVENTS.VIEWS.SHOWN, this);
}
}, {
key: "hide",
value: function hide() {
// this.iframe.style.display = "none";
this.element.style.visibility = "hidden";
this.iframe.style.visibility = "hidden";
this.stopExpanding = true;
this.emit(_constants.EVENTS.VIEWS.HIDDEN, this);
}
}, {
key: "offset",
value: function offset() {
return {
top: this.element.offsetTop,
left: this.element.offsetLeft
};
}
}, {
key: "width",
value: function width() {
return this._width;
}
}, {
key: "height",
value: function height() {
return this._height;
}
}, {
key: "position",
value: function position() {
return this.element.getBoundingClientRect();
}
}, {
key: "locationOf",
value: function locationOf(target) {
var parentPos = this.iframe.getBoundingClientRect();
var targetPos = this.contents.locationOf(target, this.settings.ignoreClass);
return {
"left": targetPos.left,
"top": targetPos.top
};
}
}, {
key: "onDisplayed",
value: function onDisplayed(view) {
// Stub, override with a custom functions
}
}, {
key: "onResize",
value: function onResize(view, e) {
// Stub, override with a custom functions
}
}, {
key: "bounds",
value: function bounds(force) {
if (force || !this.elementBounds) {
this.elementBounds = (0, _core.bounds)(this.element);
}
return this.elementBounds;
}
}, {
key: "highlight",
value: function highlight(cfiRange) {
var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var cb = arguments[2];
var _this4 = this;
var className = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : "epubjs-hl";
var styles = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
if (!this.contents) {
return;
}
var attributes = Object.assign({ "fill": "yellow", "fill-opacity": "0.3", "mix-blend-mode": "multiply" }, styles);
var range = this.contents.range(cfiRange);
var emitter = function emitter() {
_this4.emit(_constants.EVENTS.VIEWS.MARK_CLICKED, cfiRange, data);
};
data["epubcfi"] = cfiRange;
if (!this.pane) {
this.pane = new _marksPane.Pane(this.iframe, this.element);
}
var m = new _marksPane.Highlight(range, className, data, attributes);
var 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;
}
}, {
key: "underline",
value: function underline(cfiRange) {
var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var cb = arguments[2];
var _this5 = this;
var className = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : "epubjs-ul";
var styles = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
if (!this.contents) {
return;
}
var attributes = Object.assign({ "stroke": "black", "stroke-opacity": "0.3", "mix-blend-mode": "multiply" }, styles);
var range = this.contents.range(cfiRange);
var emitter = function emitter() {
_this5.emit(_constants.EVENTS.VIEWS.MARK_CLICKED, cfiRange, data);
};
data["epubcfi"] = cfiRange;
if (!this.pane) {
this.pane = new _marksPane.Pane(this.iframe, this.element);
}
var m = new _marksPane.Underline(range, className, data, attributes);
var 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;
}
}, {
key: "mark",
value: function mark(cfiRange) {
var _this6 = this;
var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var cb = arguments[2];
if (!this.contents) {
return;
}
if (cfiRange in this.marks) {
var item = this.marks[cfiRange];
return item;
}
var range = this.contents.range(cfiRange);
if (!range) {
return;
}
var container = range.commonAncestorContainer;
var parent = container.nodeType === 1 ? container : container.parentNode;
var emitter = function emitter(e) {
_this6.emit(_constants.EVENTS.VIEWS.MARK_CLICKED, cfiRange, data);
};
if (range.collapsed && container.nodeType === 1) {
range = new Range();
range.selectNodeContents(container);
} else if (range.collapsed) {
// Webkit doesn't like collapsed ranges
range = new Range();
range.selectNodeContents(parent);
}
var mark = this.document.createElement("a");
mark.setAttribute("ref", "epubjs-mk");
mark.style.position = "absolute";
mark.dataset["epubcfi"] = cfiRange;
if (data) {
Object.keys(data).forEach(function (key) {
mark.dataset[key] = data[key];
});
}
if (cb) {
mark.addEventListener("click", cb);
mark.addEventListener("touchstart", cb);
}
mark.addEventListener("click", emitter);
mark.addEventListener("touchstart", emitter);
this.placeMark(mark, range);
this.element.appendChild(mark);
this.marks[cfiRange] = { "element": mark, "range": range, "listeners": [emitter, cb] };
return parent;
}
}, {
key: "placeMark",
value: function placeMark(element, range) {
var top = void 0,
right = void 0,
left = void 0;
if (this.layout.name === "pre-paginated" || this.settings.axis !== "horizontal") {
var pos = range.getBoundingClientRect();
top = pos.top;
right = pos.right;
} else {
// Element might break columns, so find the left most element
var rects = range.getClientRects();
var rect = void 0;
for (var i = 0; i != rects.length; i++) {
rect = rects[i];
if (!left || rect.left = wait) ||
(timeSinceLastCall = maxWait));
}
function timerExpired() {
var time = now();
if (shouldInvoke(time)) {
return trailingEdge(time);
}
// Restart the timer.
timerId = setTimeout(timerExpired, remainingWait(time));
}
function trailingEdge(time) {
timerId = undefined;
// Only invoke if we have `lastArgs` which means `func` has been
// debounced at least once.
if (trailing && lastArgs) {
return invokeFunc(time);
}
lastArgs = lastThis = undefined;
return result;
}
function cancel() {
if (timerId !== undefined) {
clearTimeout(timerId);
}
lastInvokeTime = 0;
lastArgs = lastCallTime = lastThis = timerId = undefined;
}
function flush() {
return timerId === undefined ? result : trailingEdge(now());
}
function debounced() {
var time = now(),
isInvoking = shouldInvoke(time);
lastArgs = arguments;
lastThis = this;
lastCallTime = time;
if (isInvoking) {
if (timerId === undefined) {
return leadingEdge(lastCallTime);
}
if (maxing) {
// Handle invocations in a tight loop.
clearTimeout(timerId);
timerId = setTimeout(timerExpired, wait);
return invokeFunc(lastCallTime);
}
}
if (timerId === undefined) {
timerId = setTimeout(timerExpired, wait);
}
return result;
}
debounced.cancel = cancel;
debounced.flush = flush;
return debounced;
}
module.exports = debounce;
/***/ }),
/* 22 */
/***/ (function(module, exports, __webpack_require__) {
var freeGlobal = __webpack_require__(63);
/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();
module.exports = root;
/***/ }),
/* 23 */
/***/ (function(module, exports, __webpack_require__) {
var root = __webpack_require__(22);
/** Built-in value references. */
var Symbol = root.Symbol;
module.exports = Symbol;
/***/ }),
/* 24 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i 0 || distY > 0) {
this.scrollBy(distX, distY, true);
}
}
}, {
key: "afterResized",
value: function afterResized(view) {
this.emit(_constants.EVENTS.MANAGERS.RESIZE, view.section);
}
// Remove Previous Listeners if present
}, {
key: "removeShownListeners",
value: function removeShownListeners(view) {
// view.off("shown", this.afterDisplayed);
// view.off("shown", this.afterDisplayedAbove);
view.onDisplayed = function () {};
}
}, {
key: "add",
value: function add(section) {
var _this3 = this;
var view = this.createView(section);
this.views.append(view);
view.on(_constants.EVENTS.VIEWS.RESIZED, function (bounds) {
view.expanded = true;
});
view.on(_constants.EVENTS.VIEWS.AXIS, function (axis) {
_this3.updateAxis(axis);
});
// view.on(EVENTS.VIEWS.SHOWN, this.afterDisplayed.bind(this));
view.onDisplayed = this.afterDisplayed.bind(this);
view.onResize = this.afterResized.bind(this);
return view.display(this.request);
}
}, {
key: "append",
value: function append(section) {
var _this4 = this;
var view = this.createView(section);
view.on(_constants.EVENTS.VIEWS.RESIZED, function (bounds) {
view.expanded = true;
});
view.on(_constants.EVENTS.VIEWS.AXIS, function (axis) {
_this4.updateAxis(axis);
});
this.views.append(view);
view.onDisplayed = this.afterDisplayed.bind(this);
return view;
}
}, {
key: "prepend",
value: function prepend(section) {
var _this5 = this;
var view = this.createView(section);
view.on(_constants.EVENTS.VIEWS.RESIZED, function (bounds) {
_this5.counter(bounds);
view.expanded = true;
});
view.on(_constants.EVENTS.VIEWS.AXIS, function (axis) {
_this5.updateAxis(axis);
});
this.views.prepend(view);
view.onDisplayed = this.afterDisplayed.bind(this);
return view;
}
}, {
key: "counter",
value: function counter(bounds) {
if (this.settings.axis === "vertical") {
this.scrollBy(0, bounds.heightDelta, true);
} else {
this.scrollBy(bounds.widthDelta, 0, true);
}
}
}, {
key: "update",
value: function update(_offset) {
var container = this.bounds();
var views = this.views.all();
var viewsLength = views.length;
var visible = [];
var offset = typeof _offset != "undefined" ? _offset : this.settings.offset || 0;
var isVisible;
var view;
var updating = new _core.defer();
var promises = [];
for (var i = 0; i 0) {
prepend();
}
}
//default scrolling
else {
if (offset + visibleLength + delta >= contentLength) {
if (horizontal && rtl) {
prepend();
} else {
append();
}
}
if (offset - delta -1;
if (isAbsolute) {
return path;
}
if (this.path) {
resolved = this.path.resolve(path);
}
if (absolute != false && this.url) {
resolved = this.url.resolve(resolved);
}
return resolved;
}
/**
* Get a canonical link to a path
* @param {string} path
* @return {string} the canonical path string
*/
}, {
key: "canonical",
value: function canonical(path) {
var url = path;
if (!path) {
return "";
}
if (this.settings.canonical) {
url = this.settings.canonical(path);
} else {
url = this.resolve(path, true);
}
return url;
}
/**
* Determine the type of they input passed to open
* @private
* @param {string} input
* @return {string} binary | directory | epub | opf
*/
}, {
key: "determineType",
value: function determineType(input) {
var url;
var path;
var extension;
if (this.settings.encoding === "base64") {
return INPUT_TYPE.BASE64;
}
if (typeof input != "string") {
return INPUT_TYPE.BINARY;
}
url = new _url2.default(input);
path = url.path();
extension = path.extension;
// If there's a search string, remove it before determining type
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
*/
}, {
key: "unpack",
value: function unpack(packaging) {
var _this6 = this;
this.package = packaging; //TODO: deprecated this
if (this.packaging.metadata.layout === "") {
// rendition:layout not set - check display options if book is pre-paginated
this.load(this.url.resolve(IBOOKS_DISPLAY_OPTIONS_PATH)).then(function (xml) {
_this6.displayOptions = new _displayoptions2.default(xml);
_this6.loading.displayOptions.resolve(_this6.displayOptions);
}).catch(function (err) {
_this6.displayOptions = new _displayoptions2.default();
_this6.loading.displayOptions.resolve(_this6.displayOptions);
});
} else {
this.displayOptions = new _displayoptions2.default();
this.loading.displayOptions.resolve(this.displayOptions);
}
this.spine.unpack(this.packaging, this.resolve.bind(this), this.canonical.bind(this));
this.resources = new _resources2.default(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(function () {
// this.toc = this.navigation.toc;
_this6.loading.navigation.resolve(_this6.navigation);
});
if (this.packaging.coverPath) {
this.cover = this.resolve(this.packaging.coverPath);
}
// Resolve promises
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(function () {
_this6.loaded.displayOptions.then(function () {
_this6.opening.resolve(_this6);
});
}).catch(function (err) {
console.error(err);
});
} else {
// Resolve book opened promise
this.loaded.displayOptions.then(function () {
_this6.opening.resolve(_this6);
});
}
}
/**
* Load Navigation and PageList from package
* @private
* @param {Packaging} packaging
*/
}, {
key: "loadNavigation",
value: function loadNavigation(packaging) {
var _this7 = this;
var navPath = packaging.navPath || packaging.ncxPath;
var toc = packaging.toc;
// From json manifest
if (toc) {
return new Promise(function (resolve, reject) {
_this7.navigation = new _navigation2.default(toc);
if (packaging.pageList) {
_this7.pageList = new _pagelist2.default(packaging.pageList); // TODO: handle page lists from Manifest
}
resolve(_this7.navigation);
});
}
if (!navPath) {
return new Promise(function (resolve, reject) {
_this7.navigation = new _navigation2.default();
_this7.pageList = new _pagelist2.default();
resolve(_this7.navigation);
});
}
return this.load(navPath, "xml").then(function (xml) {
_this7.navigation = new _navigation2.default(xml);
_this7.pageList = new _pagelist2.default(xml);
return _this7.navigation;
});
}
/**
* Gets a Section of the Book from the Spine
* Alias for `book.spine.get`
* @param {string} target
* @return {Section}
*/
}, {
key: "section",
value: function section(target) {
return this.spine.get(target);
}
/**
* Sugar to render a book to an element
* @param {element | string} element element or string to add a rendition to
* @param {object} [options]
* @return {Rendition}
*/
}, {
key: "renderTo",
value: function renderTo(element, options) {
this.rendition = new _rendition2.default(this, options);
this.rendition.attachTo(element);
return this.rendition;
}
/**
* Set if request should use withCredentials
* @param {boolean} credentials
*/
}, {
key: "setRequestCredentials",
value: function setRequestCredentials(credentials) {
this.settings.requestCredentials = credentials;
}
/**
* Set headers request should use
* @param {object} headers
*/
}, {
key: "setRequestHeaders",
value: function setRequestHeaders(headers) {
this.settings.requestHeaders = headers;
}
/**
* Unarchive a zipped epub
* @private
* @param {binary} input epub data
* @param {string} [encoding]
* @return {Archive}
*/
}, {
key: "unarchive",
value: function unarchive(input, encoding) {
this.archive = new _archive2.default();
return this.archive.open(input, encoding);
}
/**
* Store the epubs contents
* @private
* @param {binary} input epub data
* @param {string} [encoding]
* @return {Store}
*/
}, {
key: "store",
value: function store(name) {
var _this8 = this;
// Use "blobUrl" or "base64" for replacements
var replacementsSetting = this.settings.replacements && this.settings.replacements !== "none";
// Save original url
var originalUrl = this.url;
// Save original request method
var requester = this.settings.requestMethod || _request3.default.bind(this);
// Create new Store
this.storage = new _store2.default(name, requester, this.resolve.bind(this));
// Replace request method to go through store
this.request = this.storage.request.bind(this.storage);
this.opened.then(function () {
if (_this8.archived) {
_this8.storage.requester = _this8.archive.request.bind(_this8.archive);
}
// Substitute hook
var substituteResources = function substituteResources(output, section) {
section.output = _this8.resources.substitute(output, section.url);
};
// Set to use replacements
_this8.resources.settings.replacements = replacementsSetting || "blobUrl";
// Create replacement urls
_this8.resources.replacements().then(function () {
return _this8.resources.replaceCss();
});
_this8.storage.on("offline", function () {
// Remove url to use relative resolving for hrefs
_this8.url = new _url2.default("/", "");
// Add hook to replace resources in contents
_this8.spine.hooks.serialize.register(substituteResources);
});
_this8.storage.on("online", function () {
// Restore original url
_this8.url = originalUrl;
// Remove hook
_this8.spine.hooks.serialize.deregister(substituteResources);
});
});
return this.storage;
}
/**
* Get the cover url
* @return {Promise} coverUrl
*/
}, {
key: "coverUrl",
value: function coverUrl() {
var _this9 = this;
return this.loaded.cover.then(function () {
if (!_this9.cover) {
return null;
}
if (_this9.archived) {
return _this9.archive.createUrl(_this9.cover);
} else {
return _this9.cover;
}
});
}
/**
* Load replacement urls
* @private
* @return {Promise} completed loading urls
*/
}, {
key: "replacements",
value: function replacements() {
var _this10 = this;
this.spine.hooks.serialize.register(function (output, section) {
section.output = _this10.resources.substitute(output, section.url);
});
return this.resources.replacements().then(function () {
return _this10.resources.replaceCss();
});
}
/**
* Find a DOM Range for a given CFI Range
* @param {EpubCFI} cfiRange a epub cfi range
* @return {Range}
*/
}, {
key: "getRange",
value: function getRange(cfiRange) {
var cfi = new _epubcfi2.default(cfiRange);
var item = this.spine.get(cfi.spinePos);
var _request = this.load.bind(this);
if (!item) {
return new Promise(function (resolve, reject) {
reject("CFI could not be found");
});
}
return item.load(_request).then(function (contents) {
var range = cfi.toRange(item.document);
return range;
});
}
/**
* Generates the Book Key using the identifer in the manifest or other string provided
* @param {string} [identifier] to use instead of metadata identifier
* @return {string} key
*/
}, {
key: "key",
value: function key(identifier) {
var ident = identifier || this.packaging.metadata.identifier || this.url.filename;
return "epubjs:" + _constants.EPUBJS_VERSION + ":" + ident;
}
/**
* Destroy the Book and all associated objects
*/
}, {
key: "destroy",
value: function destroy() {
this.opened = undefined;
this.loading = undefined;
this.loaded = undefined;
this.ready = undefined;
this.isOpen = false;
this.isRendered = false;
this.spine && this.spine.destroy();
this.locations && this.locations.destroy();
this.pageList && this.pageList.destroy();
this.archive && this.archive.destroy();
this.resources && this.resources.destroy();
this.container && this.container.destroy();
this.packaging && this.packaging.destroy();
this.rendition && this.rendition.destroy();
this.displayOptions && this.displayOptions.destroy();
this.spine = undefined;
this.locations = undefined;
this.pageList = undefined;
this.archive = undefined;
this.resources = undefined;
this.container = undefined;
this.packaging = undefined;
this.rendition = undefined;
this.navigation = undefined;
this.url = undefined;
this.path = undefined;
this.archived = false;
}
}]);
return Book;
}();
//-- Enable binding events to book
(0, _eventEmitter2.default)(Book.prototype);
exports.default = Book;
module.exports = exports["default"];
/***/ }),
/* 27 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var assign = __webpack_require__(28)
, normalizeOpts = __webpack_require__(36)
, isCallable = __webpack_require__(37)
, contains = __webpack_require__(38)
, d;
d = module.exports = function (dscr, value/*, options*/) {
var c, e, w, options, desc;
if ((arguments.length -1;
};
/***/ }),
/* 41 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = function (fn) {
if (typeof fn !== "function") throw new TypeError(fn + " is not a function");
return fn;
};
/***/ }),
/* 42 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_42__;
/***/ }),
/* 43 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i 0) {
var prev = this.get(prevIndex - 1);
if (prev && prev.linear) {
return prev;
}
prevIndex -= 1;
}
return;
}.bind(_this);
item.next = function () {
var nextIndex = item.index;
while (nextIndex -1) {
delete this.spineByHref[section.href];
delete this.spineById[section.idref];
return this.spineItems.splice(index, 1);
}
}
/**
* Loop over the Sections in the Spine
* @return {method} forEach
*/
}, {
key: "each",
value: function each() {
return this.spineItems.forEach.apply(this.spineItems, arguments);
}
/**
* Find the first Section in the Spine
* @return {Section} first section
*/
}, {
key: "first",
value: function first() {
var index = 0;
do {
var next = this.get(index);
if (next && next.linear) {
return next;
}
index += 1;
} while (index = 0);
}
}, {
key: "destroy",
value: function destroy() {
this.each(function (section) {
return section.destroy();
});
this.spineItems = undefined;
this.spineByHref = undefined;
this.spineById = undefined;
this.hooks.serialize.clear();
this.hooks.content.clear();
this.hooks = undefined;
this.epubcfi = undefined;
this.loaded = false;
this.items = undefined;
this.manifest = undefined;
this.spineNodeIndex = undefined;
this.baseUrl = undefined;
this.length = undefined;
}
}]);
return Spine;
}();
exports.default = Spine;
module.exports = exports["default"];
/***/ }),
/* 44 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i = 0;
var Serializer;
if (typeof XMLSerializer === "undefined" || isIE) {
Serializer = __webpack_require__(45).XMLSerializer;
} else {
Serializer = XMLSerializer;
}
var serializer = new Serializer();
this.output = serializer.serializeToString(contents);
return this.output;
}.bind(this)).then(function () {
return this.hooks.serialize.trigger(this.output, this);
}.bind(this)).then(function () {
rendering.resolve(this.output);
}.bind(this)).catch(function (error) {
rendering.reject(error);
});
return rendered;
}
/**
* Find a string in a section
* @param {string} _query The query string to find
* @return {object[]} A list of matches, with form {cfi, excerpt}
*/
}, {
key: "find",
value: function find(_query) {
var section = this;
var matches = [];
var query = _query.toLowerCase();
var find = function find(node) {
var text = node.textContent.toLowerCase();
var range = section.document.createRange();
var cfi;
var pos;
var last = -1;
var excerpt;
var limit = 150;
while (pos != -1) {
// Search for the query
pos = text.indexOf(query, last + 1);
if (pos != -1) {
// We found it! Generate a CFI
range = section.document.createRange();
range.setStart(node, pos);
range.setEnd(node, pos + query.length);
cfi = section.cfiFromRange(range);
// Generate the excerpt
if (node.textContent.length 1 && arguments[1] !== undefined ? arguments[1] : 5;
if (typeof document.createTreeWalker == "undefined") {
return this.find(_query);
}
var matches = [];
var excerptLimit = 150;
var section = this;
var query = _query.toLowerCase();
var search = function search(nodeList) {
var textWithCase = nodeList.reduce(function (acc, current) {
return acc + current.textContent;
}, "");
var text = textWithCase.toLowerCase();
var pos = text.indexOf(query);
if (pos != -1) {
var startNodeIndex = 0,
endPos = pos + query.length;
var endNodeIndex = 0,
l = 0;
if (pos endPos ? endPos : endPos - beforeEndLengthCount);
cfi = section.cfiFromRange(range);
var excerpt = nodeList.slice(0, endNodeIndex + 1).reduce(function (acc, current) {
return acc + current.textContent;
}, "");
if (excerpt.length > excerptLimit) {
excerpt = excerpt.substring(pos - excerptLimit / 2, pos + excerptLimit / 2);
excerpt = "..." + excerpt + "...";
}
matches.push({
cfi: cfi,
excerpt: excerpt
});
}
}
};
var treeWalker = document.createTreeWalker(section.document, NodeFilter.SHOW_TEXT, null, false);
var node = void 0,
nodeList = [];
while (node = treeWalker.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 properies with
* the global layout properities.
* @param {object} globalLayout The global layout settings object, chapter properties string
* @return {object} layoutProperties Object with layout properties
*/
}, {
key: "reconcileLayoutSettings",
value: function reconcileLayoutSettings(globalLayout) {
//-- Get the global defaults
var settings = {
layout: globalLayout.layout,
spread: globalLayout.spread,
orientation: globalLayout.orientation
};
//-- Get the chapter's display type
this.properties.forEach(function (prop) {
var rendition = prop.replace("rendition:", "");
var split = rendition.indexOf("-");
var property, value;
if (split != -1) {
property = rendition.slice(0, split);
value = rendition.slice(split + 1);
settings[property] = value;
}
});
return settings;
}
/**
* Get a CFI from a Range in the Section
* @param {range} _range
* @return {string} cfi an EpubCFI string
*/
}, {
key: "cfiFromRange",
value: function cfiFromRange(_range) {
return new _epubcfi2.default(_range, this.cfiBase).toString();
}
/**
* Get a CFI from an Element in the Section
* @param {element} el
* @return {string} cfi an EpubCFI string
*/
}, {
key: "cfiFromElement",
value: function cfiFromElement(el) {
return new _epubcfi2.default(el, this.cfiBase).toString();
}
/**
* Unload the section document
*/
}, {
key: "unload",
value: function unload() {
this.document = undefined;
this.contents = undefined;
this.output = undefined;
}
}, {
key: "destroy",
value: function destroy() {
this.unload();
this.hooks.serialize.clear();
this.hooks.content.clear();
this.hooks = undefined;
this.idref = undefined;
this.linear = undefined;
this.properties = undefined;
this.index = undefined;
this.href = undefined;
this.url = undefined;
this.next = undefined;
this.prev = undefined;
this.cfiBase = undefined;
}
}]);
return Section;
}();
exports.default = Section;
module.exports = exports["default"];
/***/ }),
/* 45 */
/***/ (function(module, exports, __webpack_require__) {
function DOMParser(options){
this.options = options ||{locator:{}};
}
DOMParser.prototype.parseFromString = function(source,mimeType){
var options = this.options;
var sax = new XMLReader();
var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler
var errorHandler = options.errorHandler;
var locator = options.locator;
var defaultNSMap = options.xmlns||{};
var entityMap = {'lt':'','amp':'&','quot':'"','apos':"'"}
if(locator){
domBuilder.setDocumentLocator(locator)
}
sax.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator);
sax.domBuilder = options.domBuilder || domBuilder;
if(/\/x?html?$/.test(mimeType)){
entityMap.nbsp = '\xa0';
entityMap.copy = '\xa9';
defaultNSMap['']= 'http://www.w3.org/1999/xhtml';
}
defaultNSMap.xml = defaultNSMap.xml || 'http://www.w3.org/XML/1998/namespace';
if(source){
sax.parse(source,defaultNSMap,entityMap);
}else{
sax.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+']\t'+msg+_locator(locator));
}||function(){};
}
build('warning');
build('error');
build('fatalError');
return errorHandler;
}
//console.log('#\n\n\n\n\n\n\n####')
/**
* +ContentHandler+ErrorHandler
* +LexicalHandler+EntityResolver2
* -DeclHandler-DTDHandler
*
* DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler
* DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2
* @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html
*/
function DOMHandler() {
this.cdata = false;
}
function position(locator,node){
node.lineNumber = locator.lineNumber;
node.columnNumber = locator.columnNumber;
}
/**
* @see org.xml.sax.ContentHandler#startDocument
* @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
*/
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 = start+length || start){
return new java.lang.String(chars,start,length)+'';
}
return chars;
}
}
/*
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html
* used method of org.xml.sax.ext.LexicalHandler:
* #comment(chars, start, length)
* #startCDATA()
* #endCDATA()
* #startDTD(name, publicId, systemId)
*
*
* IGNORED method of org.xml.sax.ext.LexicalHandler:
* #endDTD()
* #startEntity(name)
* #endEntity(name)
*
*
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html
* IGNORED method of org.xml.sax.ext.DeclHandler
* #attributeDecl(eName, aName, type, mode, value)
* #elementDecl(name, model)
* #externalEntityDecl(name, publicId, systemId)
* #internalEntityDecl(name, value)
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html
* IGNORED method of org.xml.sax.EntityResolver2
* #resolveEntity(String name,String publicId,String baseURI,String systemId)
* #resolveEntity(publicId, systemId)
* #getExternalSubset(name, baseURI)
* @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html
* IGNORED method of org.xml.sax.DTDHandler
* #notationDecl(name, publicId, systemId) {};
* #unparsedEntityDecl(name, publicId, systemId, notationName) {};
*/
"endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){
DOMHandler.prototype[key] = function(){return null}
})
/* Private static helpers treated below as private instance methods, so don't need to add these to the public API; we might use a Relator to also get rid of non-standard public properties */
function appendElement (hander,node) {
if (!hander.currentElement) {
hander.doc.appendChild(node);
} else {
hander.currentElement.appendChild(node);
}
}//appendChild and setAttributeNS are preformance key
//if(typeof require == 'function'){
var XMLReader = __webpack_require__(46).XMLReader;
var DOMImplementation = exports.DOMImplementation = __webpack_require__(17).DOMImplementation;
exports.XMLSerializer = __webpack_require__(17).XMLSerializer ;
exports.DOMParser = DOMParser;
//}
/***/ }),
/* 46 */
/***/ (function(module, exports) {
//[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
//[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
//[5] Name ::= NameStartChar (NameChar)*
var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]///\u10000-\uEFFFF
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 tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
//var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',')
//S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE
//S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
var S_TAG = 0;//tag name offerring
var S_ATTR = 1;//attr name offerring
var S_ATTR_SPACE=2;//attr name end and space offer
var S_EQ = 3;//=space?
var S_ATTR_NOQUOT_VALUE = 4;//attr value(no quot value only)
var S_ATTR_END = 5;//attr value end and no space(quot end)
var S_TAG_SPACE = 6;//(attr value end || tag end ) && (space offer)
var S_TAG_CLOSE = 7;//closed el
function XMLReader(){
}
XMLReader.prototype = {
parse:function(source,defaultNSMap,entityMap){
var domBuilder = this.domBuilder;
domBuilder.startDocument();
_copy(defaultNSMap ,defaultNSMap = {})
parse(source,defaultNSMap,entityMap,
domBuilder,this.errorHandler);
domBuilder.endDocument();
}
}
function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
function fixedFromCharCode(code) {
// String.prototype.fromCharCode does not supports
// > 2 bytes unicode chars directly
if (code > 0xffff) {
code -= 0x10000;
var surrogate1 = 0xd800 + (code >> 10)
, surrogate2 = 0xdc00 + (code & 0x3ff);
return String.fromCharCode(surrogate1, surrogate2);
} else {
return String.fromCharCode(code);
}
}
function entityReplacer(a){
var k = a.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:'+a);
return a;
}
}
function appendText(end){//has some bugs
if(end>start){
var xt = source.substring(start,end).replace(/?\w+;/g,entityReplacer);
locator&&position(start);
domBuilder.characters(xt,0,end-start);
start = end
}
}
function position(p,m){
while(p>=lineEnd && (m = linePattern.exec(source))){
lineStart = m.index;
lineEnd = lineStart + m[0].length;
locator.lineNumber++;
//console.log('line++:',locator,startPos,endPos)
}
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){
appendText(tagStart);
}
switch(source.charAt(tagStart+1)){
case '/':
var end = source.indexOf('>',tagStart+3);
var tagName = source.substring(tagStart+2,end);
var config = parseStack.pop();
if(end
locator&&position(tagStart);
end = parseInstruction(source,tagStart,domBuilder);
break;
case '!':// start){
start = end;
}else{
//TODO: 这里有可能sax回退,有位置错误风险
appendText(Math.max(tagStart,start)+1);
}
}
}
function copyLocator(f,t){
t.lineNumber = f.lineNumber;
t.columnNumber = f.columnNumber;
return t;
}
/**
* @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
* @return end of the elementStartPart(end of elementEndPart for selfClosed el)
*/
function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,errorHandler){
var attrName;
var value;
var p = ++start;
var s = S_TAG;//status
while(true){
var c = source.charAt(p);
switch(c){
case '=':
if(s === S_ATTR){//attrName
attrName = source.slice(start,p);
s = S_EQ;
}else if(s === S_ATTR_SPACE){
s = S_EQ;
}else{
//fatalError: equal must after attrName or space after attrName
throw new Error('attribute equal must after attrName');
}
break;
case '\'':
case '"':
if(s === S_EQ || s === S_ATTR //|| s == S_ATTR_SPACE
){//equal
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);
el.add(attrName,value,start-1);
s = S_ATTR_END;
}else{
//fatalError: no end quot match
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);
//console.log(attrName,value,start,p)
el.add(attrName,value,start);
//console.dir(el)
errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
start = p+1;
s = S_ATTR_END
}else{
//fatalError: no equal before
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:
case S_ATTR_SPACE:
break;
//case S_EQ:
default:
throw new Error("attribute invalid close char('/')")
}
break;
case ''://end document
//throw new Error('unexpected end of input')
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;//normal
case S_ATTR_NOQUOT_VALUE://Compatible state
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(")!!');
el.add(attrName,value.replace(/?\w+;/g,entityReplacer),start)
}else{
if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !value.match(/^(?:disabled|checked|selected)$/i)){
errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!')
}
el.add(value,value,start)
}
break;
case S_EQ:
throw new Error('attribute value missed!!');
}
// console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
return p;
/*xml space '\x20' | #x9 | #xD | #xA; */
case '\u0080':
c = ' ';
default:
if(c' must be connected to");
}
}
}//end outer switch
//console.log('p++',p)
p++;
}
}
/**
* @return true if has new namespace define
*/
function appendElement(el,domBuilder,currentNSMap){
var tagName = el.tagName;
var localNSMap = null;
//var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
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' && ''
}
//can not set prefix,because prefix !== ''
a.localName = localName ;
//prefix == null for no ns prefix attribute
if(nsPrefix !== false){//hack!!
if(localNSMap == null){
localNSMap = {}
//console.log(currentNSMap,0)
_copy(currentNSMap,currentNSMap={})
//console.log(currentNSMap,1)
}
currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
a.uri = 'http://www.w3.org/2000/xmlns/'
domBuilder.startPrefixMapping(nsPrefix, value)
}
}
var i = el.length;
while(i--){
a = el[i];
var prefix = a.prefix;
if(prefix){//no prefix attribute has no namespace
if(prefix === 'xml'){
a.uri = 'http://www.w3.org/XML/1998/namespace';
}if(prefix !== 'xmlns'){
a.uri = currentNSMap[prefix || '']
//{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
}
}
}
var nsp = tagName.indexOf(':');
if(nsp>0){
prefix = el.prefix = tagName.slice(0,nsp);
localName = el.localName = tagName.slice(nsp+1);
}else{
prefix = null;//important!!
localName = el.localName = tagName;
}
//no prefix element has default namespace
var ns = el.uri = currentNSMap[prefix || ''];
domBuilder.startElement(ns,localName,tagName,el);
//endPrefixMapping and startPrefixMapping have not any help for dom builder
//localNSMap = null
if(el.closed){
domBuilder.endElement(ns,localName,tagName);
if(localNSMap){
for(prefix in localNSMap){
domBuilder.endPrefixMapping(prefix)
}
}
}else{
el.currentNSMap = currentNSMap;
el.localNSMap = localNSMap;
//parseStack.push(el);
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)){
//lexHandler.startCDATA();
domBuilder.characters(text,0,text.length);
//lexHandler.endCDATA();
return elEndStart;
//}
}//}else{//text area
text = text.replace(/?\w+;/g,entityReplacer);
domBuilder.characters(text,0,text.length);
return elEndStart;
//}
}
}
return elStartEnd+1;
}
function fixSelfClosed(source,elStartEnd,tagName,closeMap){
//if(tagName in closeMap){
var pos = closeMap[tagName];
if(pos == null){
//console.log(tagName)
pos = source.lastIndexOf(''+tagName+'>')
if(pos',start+4);
//append comment source.substring(4,end)// https://davidwalsh.name/add-rules-stylesheets
style.appendChild(document.createTextNode(""));
document.head.appendChild(style);
return style.sheet;
}
}, {
key: "addStyleRules",
value: function addStyleRules(selector, rulesArray) {
var scope = "#" + this.id + " ";
var rules = "";
if (!this.sheet) {
this.sheet = this.getSheet();
}
rulesArray.forEach(function (set) {
for (var prop in set) {
if (set.hasOwnProperty(prop)) {
rules += prop + ":" + set[prop] + ";";
}
}
});
this.sheet.insertRule(scope + selector + " {" + rules + "}", 0);
}
}, {
key: "axis",
value: function axis(_axis) {
if (_axis === "horizontal") {
this.container.style.display = "flex";
this.container.style.flexDirection = "row";
this.container.style.flexWrap = "nowrap";
} else {
this.container.style.display = "block";
}
this.settings.axis = _axis;
}
// orientation(orientation) {
// if (orientation === "landscape") {
//
// } else {
//
// }
//
// this.orientation = orientation;
// }
}, {
key: "direction",
value: function direction(dir) {
if (this.container) {
this.container.dir = dir;
this.container.style["direction"] = dir;
}
if (this.settings.fullsize) {
document.body.style["direction"] = dir;
}
this.settings.dir = dir;
}
}, {
key: "overflow",
value: function 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;
}
}, {
key: "destroy",
value: function destroy() {
var base;
if (this.element) {
if (this.settings.hidden) {
base = this.wrapper;
} else {
base = this.container;
}
if (this.element.contains(this.container)) {
this.element.removeChild(this.container);
}
window.removeEventListener("resize", this.resizeFunc);
window.removeEventListener("orientationChange", this.orientationChangeFunc);
}
}
}]);
return Stage;
}();
exports.default = Stage;
module.exports = exports["default"];
/***/ }),
/* 61 */
/***/ (function(module, exports, __webpack_require__) {
var debounce = __webpack_require__(21),
isObject = __webpack_require__(16);
/** Error message constants. */
var FUNC_ERROR_TEXT = 'Expected a function';
/**
* Creates a throttled function that only invokes `func` at most once per
* every `wait` milliseconds. The throttled function comes with a `cancel`
* method to cancel delayed `func` invocations and a `flush` method to
* immediately invoke them. Provide `options` to indicate whether `func`
* should be invoked on the leading and/or trailing edge of the `wait`
* timeout. The `func` is invoked with the last arguments provided to the
* throttled function. Subsequent calls to the throttled function return the
* result of the last `func` invocation.
*
* **Note:** If `leading` and `trailing` options are `true`, `func` is
* invoked on the trailing edge of the timeout only if the throttled function
* is invoked more than once during the `wait` timeout.
*
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
*
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
* for details over the differences between `_.throttle` and `_.debounce`.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Function
* @param {Function} func The function to throttle.
* @param {number} [wait=0] The number of milliseconds to throttle invocations to.
* @param {Object} [options={}] The options object.
* @param {boolean} [options.leading=true]
* Specify invoking on the leading edge of the timeout.
* @param {boolean} [options.trailing=true]
* Specify invoking on the trailing edge of the timeout.
* @returns {Function} Returns the new throttled function.
* @example
*
* // Avoid excessively updating the position while scrolling.
* jQuery(window).on('scroll', _.throttle(updatePosition, 100));
*
* // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
* var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
* jQuery(element).on('click', throttled);
*
* // Cancel the trailing throttled invocation.
* jQuery(window).on('popstate', throttled.cancel);
*/
function throttle(func, wait, options) {
var leading = true,
trailing = true;
if (typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
if (isObject(options)) {
leading = 'leading' in options ? !!options.leading : leading;
trailing = 'trailing' in options ? !!options.trailing : trailing;
}
return debounce(func, wait, {
'leading': leading,
'maxWait': wait,
'trailing': trailing
});
}
module.exports = throttle;
/***/ }),
/* 62 */
/***/ (function(module, exports, __webpack_require__) {
var root = __webpack_require__(22);
/**
* Gets the timestamp of the number of milliseconds that have elapsed since
* the Unix epoch (1 January 1970 00:00:00 UTC).
*
* @static
* @memberOf _
* @since 2.4.0
* @category Date
* @returns {number} Returns the timestamp.
* @example
*
* _.defer(function(stamp) {
* console.log(_.now() - stamp);
* }, _.now());
* // => Logs the number of milliseconds it took for the deferred invocation.
*/
var now = function() {
return root.Date.now();
};
module.exports = now;
/***/ }),
/* 63 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
module.exports = freeGlobal;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(5)))
/***/ }),
/* 64 */
/***/ (function(module, exports, __webpack_require__) {
var isObject = __webpack_require__(16),
isSymbol = __webpack_require__(65);
/** Used as references for various `Number` constants. */
var NAN = 0 / 0;
/** Used to match leading and trailing whitespace. */
var reTrim = /^\s+|\s+$/g;
/** Used to detect bad signed hexadecimal string values. */
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
/** Used to detect binary string values. */
var reIsBinary = /^0b[01]+$/i;
/** Used to detect octal string values. */
var reIsOctal = /^0o[0-7]+$/i;
/** Built-in method references without a dependency on `root`. */
var freeParseInt = parseInt;
/**
* Converts `value` to a number.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to process.
* @returns {number} Returns the number.
* @example
*
* _.toNumber(3.2);
* // => 3.2
*
* _.toNumber(Number.MIN_VALUE);
* // => 5e-324
*
* _.toNumber(Infinity);
* // => Infinity
*
* _.toNumber('3.2');
* // => 3.2
*/
function toNumber(value) {
if (typeof value == 'number') {
return value;
}
if (isSymbol(value)) {
return NAN;
}
if (isObject(value)) {
var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
value = isObject(other) ? (other + '') : other;
}
if (typeof value != 'string') {
return value === 0 ? value : +value;
}
value = value.replace(reTrim, '');
var isBinary = reIsBinary.test(value);
return (isBinary || reIsOctal.test(value))
? freeParseInt(value.slice(2), isBinary ? 2 : 8)
: (reIsBadHex.test(value) ? NAN : +value);
}
module.exports = toNumber;
/***/ }),
/* 65 */
/***/ (function(module, exports, __webpack_require__) {
var baseGetTag = __webpack_require__(66),
isObjectLike = __webpack_require__(69);
/** `Object#toString` result references. */
var symbolTag = '[object Symbol]';
/**
* Checks if `value` is classified as a `Symbol` primitive or object.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
* @example
*
* _.isSymbol(Symbol.iterator);
* // => true
*
* _.isSymbol('abc');
* // => false
*/
function isSymbol(value) {
return typeof value == 'symbol' ||
(isObjectLike(value) && baseGetTag(value) == symbolTag);
}
module.exports = isSymbol;
/***/ }),
/* 66 */
/***/ (function(module, exports, __webpack_require__) {
var Symbol = __webpack_require__(23),
getRawTag = __webpack_require__(67),
objectToString = __webpack_require__(68);
/** `Object#toString` result references. */
var nullTag = '[object Null]',
undefinedTag = '[object Undefined]';
/** Built-in value references. */
var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
/**
* The base implementation of `getTag` without fallbacks for buggy environments.
*
* @private
* @param {*} value The value to query.
* @returns {string} Returns the `toStringTag`.
*/
function baseGetTag(value) {
if (value == null) {
return value === undefined ? undefinedTag : nullTag;
}
return (symToStringTag && symToStringTag in Object(value))
? getRawTag(value)
: objectToString(value);
}
module.exports = baseGetTag;
/***/ }),
/* 67 */
/***/ (function(module, exports, __webpack_require__) {
var Symbol = __webpack_require__(23);
/** Used for built-in method references. */
var objectProto = Object.prototype;
/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;
/**
* Used to resolve the
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
* of values.
*/
var nativeObjectToString = objectProto.toString;
/** Built-in value references. */
var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
/**
* A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
*
* @private
* @param {*} value The value to query.
* @returns {string} Returns the raw `toStringTag`.
*/
function getRawTag(value) {
var isOwn = hasOwnProperty.call(value, symToStringTag),
tag = value[symToStringTag];
try {
value[symToStringTag] = undefined;
var unmasked = true;
} catch (e) {}
var result = nativeObjectToString.call(value);
if (unmasked) {
if (isOwn) {
value[symToStringTag] = tag;
} else {
delete value[symToStringTag];
}
}
return result;
}
module.exports = getRawTag;
/***/ }),
/* 68 */
/***/ (function(module, exports) {
/** Used for built-in method references. */
var objectProto = Object.prototype;
/**
* Used to resolve the
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
* of values.
*/
var nativeObjectToString = objectProto.toString;
/**
* Converts `value` to a string using `Object.prototype.toString`.
*
* @private
* @param {*} value The value to convert.
* @returns {string} Returns the converted string.
*/
function objectToString(value) {
return nativeObjectToString.call(value);
}
module.exports = objectToString;
/***/ }),
/* 69 */
/***/ (function(module, exports) {
/**
* Checks if `value` is object-like. A value is object-like if it's not `null`
* and has a `typeof` result of "object".
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
* @example
*
* _.isObjectLike({});
* // => true
*
* _.isObjectLike([1, 2, 3]);
* // => true
*
* _.isObjectLike(_.noop);
* // => false
*
* _.isObjectLike(null);
* // => false
*/
function isObjectLike(value) {
return value != null && typeof value == 'object';
}
module.exports = isObjectLike;
/***/ }),
/* 70 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i -1) {
this._views.splice(index, 1);
}
this.destroy(view);
this.length--;
}
}, {
key: "destroy",
value: function destroy(view) {
if (view.displayed) {
view.destroy();
}
if (this.container) {
this.container.removeChild(view.element);
}
view = null;
}
// Iterators
}, {
key: "forEach",
value: function forEach() {
return this._views.forEach.apply(this._views, arguments);
}
}, {
key: "clear",
value: function clear() {
// Remove all views
var view;
var len = this.length;
if (!this.length) return;
for (var i = 0; i = snapWidth) {
return 0;
}
if (velocity > minVelocity) {
// previous
return -1;
} else if (velocity 0 && arguments[0] !== undefined ? arguments[0] : 0;
var left = this.scrollLeft;
var snapWidth = this.layout.pageWidth * this.layout.divisor;
var snapTo = Math.round(left / snapWidth) * snapWidth;
if (howMany) {
snapTo += howMany * snapWidth;
}
return this.smoothScrollTo(snapTo);
}
}, {
key: "smoothScrollTo",
value: function smoothScrollTo(destination) {
var deferred = new _core.defer();
var start = this.scrollLeft;
var startTime = this.now();
var duration = this.settings.duration;
var easing = this.settings.easing;
this.snapping = true;
// add animation loop
function tick() {
var now = this.now();
var time = Math.min(1, (now - startTime) / duration);
var timeFunction = easing(time);
if (this.touchCanceler || this.resizeCanceler) {
this.resizeCanceler = false;
this.snapping = false;
deferred.resolve();
return;
}
if (time 0 && arguments[0] !== undefined ? arguments[0] : 0;
var top = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
if (this.fullsize) {
window.scroll(left, top);
} else {
this.scroller.scrollLeft = left;
this.scroller.scrollTop = top;
}
}
}, {
key: "now",
value: function now() {
return 'now' in window.performance ? performance.now() : new Date().getTime();
}
}, {
key: "destroy",
value: function destroy() {
if (!this.scroller) {
return;
}
if (this.fullsize) {
this.enableScroll();
}
this.removeListeners();
this.scroller = undefined;
}
}]);
return Snap;
}();
(0, _eventEmitter2.default)(Snap.prototype);
exports.default = Snap;
module.exports = exports["default"];
/***/ }),
/* 72 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i }
*/
}, {
key: "request",
value: function request(url, type) {
var deferred = new _core.defer();
var response;
var path = new _path2.default(url);
// If type isn't set, determine it from the file extension
if (!type) {
type = path.extension;
}
if (type == "blob") {
response = this.getBlob(url);
} else {
response = this.getText(url);
}
if (response) {
response.then(function (r) {
var result = this.handleResponse(r, type);
deferred.resolve(result);
}.bind(this));
} else {
deferred.reject({
message: "File not found in the epub: " + url,
stack: new Error().stack
});
}
return deferred.promise;
}
/**
* Handle the response from request
* @private
* @param {any} response
* @param {string} [type]
* @return {any} the parsed result
*/
}, {
key: "handleResponse",
value: function handleResponse(response, type) {
var r;
if (type == "json") {
r = JSON.parse(response);
} else if ((0, _core.isXml)(type)) {
r = (0, _core.parse)(response, "text/xml");
} else if (type == "xhtml") {
r = (0, _core.parse)(response, "application/xhtml+xml");
} else if (type == "html" || type == "htm") {
r = (0, _core.parse)(response, "text/html");
} else {
r = response;
}
return r;
}
/**
* Get a Blob from Archive by Url
* @param {string} url
* @param {string} [mimeType]
* @return {Blob}
*/
}, {
key: "getBlob",
value: function getBlob(url, mimeType) {
var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash
var entry = this.zip.file(decodededUrl);
if (entry) {
mimeType = mimeType || _mime2.default.lookup(entry.name);
return entry.async("uint8array").then(function (uint8array) {
return new Blob([uint8array], { type: mimeType });
});
}
}
/**
* Get Text from Archive by Url
* @param {string} url
* @param {string} [encoding]
* @return {string}
*/
}, {
key: "getText",
value: function getText(url, encoding) {
var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash
var entry = this.zip.file(decodededUrl);
if (entry) {
return entry.async("string").then(function (text) {
return text;
});
}
}
/**
* Get a base64 encoded result from Archive by Url
* @param {string} url
* @param {string} [mimeType]
* @return {string} base64 encoded
*/
}, {
key: "getBase64",
value: function getBase64(url, mimeType) {
var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash
var entry = this.zip.file(decodededUrl);
if (entry) {
mimeType = mimeType || _mime2.default.lookup(entry.name);
return entry.async("base64").then(function (data) {
return "data:" + mimeType + ";base64," + data;
});
}
}
/**
* Create a Url from an unarchived item
* @param {string} url
* @param {object} [options.base64] use base64 encoding or blob url
* @return {Promise} url promise with Url string
*/
}, {
key: "createUrl",
value: function createUrl(url, options) {
var deferred = new _core.defer();
var _URL = window.URL || window.webkitURL || window.mozURL;
var tempUrl;
var response;
var useBase64 = options && options.base64;
if (url in this.urlCache) {
deferred.resolve(this.urlCache[url]);
return deferred.promise;
}
if (useBase64) {
response = this.getBase64(url);
if (response) {
response.then(function (tempUrl) {
this.urlCache[url] = tempUrl;
deferred.resolve(tempUrl);
}.bind(this));
}
} else {
response = this.getBlob(url);
if (response) {
response.then(function (blob) {
tempUrl = _URL.createObjectURL(blob);
this.urlCache[url] = tempUrl;
deferred.resolve(tempUrl);
}.bind(this));
}
}
if (!response) {
deferred.reject({
message: "File not found in the epub: " + url,
stack: new Error().stack
});
}
return deferred.promise;
}
/**
* Revoke Temp Url for a achive item
* @param {string} url url of the item in the archive
*/
}, {
key: "revokeUrl",
value: function revokeUrl(url) {
var _URL = window.URL || window.webkitURL || window.mozURL;
var fromCache = this.urlCache[url];
if (fromCache) _URL.revokeObjectURL(fromCache);
}
}, {
key: "destroy",
value: function destroy() {
var _URL = window.URL || window.webkitURL || window.mozURL;
for (var fromCache in this.urlCache) {
_URL.revokeObjectURL(fromCache);
}
this.zip = undefined;
this.urlCache = {};
}
}]);
return Archive;
}();
exports.default = Archive;
module.exports = exports["default"];
/***/ }),
/* 73 */
/***/ (function(module, exports) {
if(typeof __WEBPACK_EXTERNAL_MODULE_73__ === 'undefined') {var e = new Error("Cannot find module \"jszip\""); e.code = 'MODULE_NOT_FOUND'; throw e;}
module.exports = __WEBPACK_EXTERNAL_MODULE_73__;
/***/ }),
/* 74 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i } store objects
*/
}, {
key: "add",
value: function add(resources, force) {
var _this = this;
var mapped = resources.resources.map(function (item) {
var href = item.href;
var url = _this.resolver(href);
var encodedUrl = window.encodeURIComponent(url);
return _this.storage.getItem(encodedUrl).then(function (item) {
if (!item || force) {
return _this.requester(url, "binary").then(function (data) {
return _this.storage.setItem(encodedUrl, data);
});
} else {
return item;
}
});
});
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}
*/
}, {
key: "put",
value: function put(url, withCredentials, headers) {
var _this2 = this;
var encodedUrl = window.encodeURIComponent(url);
return this.storage.getItem(encodedUrl).then(function (result) {
if (!result) {
return _this2.requester(url, "binary", withCredentials, headers).then(function (data) {
return _this2.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}
*/
}, {
key: "request",
value: function request(url, type, withCredentials, headers) {
var _this3 = this;
if (this.online) {
// From network
return this.requester(url, type, withCredentials, headers).then(function (data) {
// save to store if not present
_this3.put(url);
return data;
});
} else {
// From store
return this.retrieve(url, type);
}
}
/**
* 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}
*/
}, {
key: "retrieve",
value: function retrieve(url, type) {
var _this4 = this;
var deferred = new _core.defer();
var response;
var path = new _path2.default(url);
// If type isn't set, determine it from the file extension
if (!type) {
type = path.extension;
}
if (type == "blob") {
response = this.getBlob(url);
} else {
response = this.getText(url);
}
return response.then(function (r) {
var deferred = new _core.defer();
var result;
if (r) {
result = _this4.handleResponse(r, type);
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
*/
}, {
key: "handleResponse",
value: function handleResponse(response, type) {
var r;
if (type == "json") {
r = JSON.parse(response);
} else if ((0, _core.isXml)(type)) {
r = (0, _core.parse)(response, "text/xml");
} else if (type == "xhtml") {
r = (0, _core.parse)(response, "application/xhtml+xml");
} else if (type == "html" || type == "htm") {
r = (0, _core.parse)(response, "text/html");
} else {
r = response;
}
return r;
}
/**
* Get a Blob from Storage by Url
* @param {string} url
* @param {string} [mimeType]
* @return {Blob}
*/
}, {
key: "getBlob",
value: function getBlob(url, mimeType) {
var encodedUrl = window.encodeURIComponent(url);
return this.storage.getItem(encodedUrl).then(function (uint8array) {
if (!uint8array) return;
mimeType = mimeType || _mime2.default.lookup(url);
return new Blob([uint8array], { type: mimeType });
});
}
/**
* Get Text from Storage by Url
* @param {string} url
* @param {string} [mimeType]
* @return {string}
*/
}, {
key: "getText",
value: function getText(url, mimeType) {
var encodedUrl = window.encodeURIComponent(url);
mimeType = mimeType || _mime2.default.lookup(url);
return this.storage.getItem(encodedUrl).then(function (uint8array) {
var deferred = new _core.defer();
var reader = new FileReader();
var blob;
if (!uint8array) return;
blob = new Blob([uint8array], { type: mimeType });
reader.addEventListener("loadend", function () {
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
*/
}, {
key: "getBase64",
value: function getBase64(url, mimeType) {
var encodedUrl = window.encodeURIComponent(url);
mimeType = mimeType || _mime2.default.lookup(url);
return this.storage.getItem(encodedUrl).then(function (uint8array) {
var deferred = new _core.defer();
var reader = new FileReader();
var blob;
if (!uint8array) return;
blob = new Blob([uint8array], { type: mimeType });
reader.addEventListener("loadend", function () {
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
*/
}, {
key: "createUrl",
value: function createUrl(url, options) {
var deferred = new _core.defer();
var _URL = window.URL || window.webkitURL || window.mozURL;
var tempUrl;
var response;
var useBase64 = options && options.base64;
if (url in this.urlCache) {
deferred.resolve(this.urlCache[url]);
return deferred.promise;
}
if (useBase64) {
response = this.getBase64(url);
if (response) {
response.then(function (tempUrl) {
this.urlCache[url] = tempUrl;
deferred.resolve(tempUrl);
}.bind(this));
}
} else {
response = this.getBlob(url);
if (response) {
response.then(function (blob) {
tempUrl = _URL.createObjectURL(blob);
this.urlCache[url] = tempUrl;
deferred.resolve(tempUrl);
}.bind(this));
}
}
if (!response) {
deferred.reject({
message: "File not found in storage: " + url,
stack: new Error().stack
});
}
return deferred.promise;
}
/**
* Revoke Temp Url for a achive item
* @param {string} url url of the item in the store
*/
}, {
key: "revokeUrl",
value: function revokeUrl(url) {
var _URL = window.URL || window.webkitURL || window.mozURL;
var fromCache = this.urlCache[url];
if (fromCache) _URL.revokeObjectURL(fromCache);
}
}, {
key: "destroy",
value: function destroy() {
var _URL = window.URL || window.webkitURL || window.mozURL;
for (var fromCache in this.urlCache) {
_URL.revokeObjectURL(fromCache);
}
this.urlCache = {};
this.removeListeners();
}
}]);
return Store;
}();
(0, _eventEmitter2.default)(Store.prototype);
exports.default = Store;
module.exports = exports["default"];
/***/ }),
/* 75 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(global) {var require;var require;/*!
localForage -- Offline Storage, Improved
Version 1.7.3
https://localforage.github.io/localForage
(c) 2013-2017 Mozilla, Apache License 2.0
*/
(function(f){if(true){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.localforage = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return require(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw (f.code="MODULE_NOT_FOUND", f)}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o element; its readystatechange event will be fired asynchronously once it is inserted
// into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
var scriptEl = global.document.createElement('script');
scriptEl.onreadystatechange = function () {
nextTick();
scriptEl.onreadystatechange = null;
scriptEl.parentNode.removeChild(scriptEl);
scriptEl = null;
};
global.document.documentElement.appendChild(scriptEl);
};
} else {
scheduleDrain = function () {
setTimeout(nextTick, 0);
};
}
}
var draining;
var queue = [];
//named nextTick for less confusing stack traces
function nextTick() {
draining = true;
var i, oldQueue;
var len = queue.length;
while (len) {
oldQueue = queue;
queue = [];
i = -1;
while (++i = 43);
};
})["catch"](function () {
return false; // error, so assume unsupported
});
}
function _checkBlobSupport(idb) {
if (typeof supportsBlobs === 'boolean') {
return Promise$1.resolve(supportsBlobs);
}
return _checkBlobSupportWithoutCaching(idb).then(function (value) {
supportsBlobs = value;
return supportsBlobs;
});
}
function _deferReadiness(dbInfo) {
var dbContext = dbContexts[dbInfo.name];
// Create a deferred object representing the current database operation.
var deferredOperation = {};
deferredOperation.promise = new Promise$1(function (resolve, reject) {
deferredOperation.resolve = resolve;
deferredOperation.reject = reject;
});
// Enqueue the deferred operation.
dbContext.deferredOperations.push(deferredOperation);
// Chain its promise to the database readiness.
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];
// Dequeue a deferred operation.
var deferredOperation = dbContext.deferredOperations.pop();
// Resolve its promise (which is part of the database readiness
// chain of promises).
if (deferredOperation) {
deferredOperation.resolve();
return deferredOperation.promise;
}
}
function _rejectReadiness(dbInfo, err) {
var dbContext = dbContexts[dbInfo.name];
// Dequeue a deferred operation.
var deferredOperation = dbContext.deferredOperations.pop();
// Reject its promise (which is part of the database readiness
// chain of promises).
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 dbInfo.db.version;
if (isDowngrade) {
// If the version is not the default one
// then warn for impossible downgrade.
if (dbInfo.version !== defaultVersion) {
console.warn('The database "' + dbInfo.name + '"' + " can't be downgraded from version " + dbInfo.db.version + ' to version ' + dbInfo.version + '.');
}
// Align the versions to prevent errors.
dbInfo.version = dbInfo.db.version;
}
if (isUpgrade || isNewStore) {
// If the store is new then increment the version (if needed).
// This will trigger an "upgradeneeded" event which is required
// for creating a store.
if (isNewStore) {
var incVersion = dbInfo.db.version + 1;
if (incVersion > dbInfo.version) {
dbInfo.version = incVersion;
}
}
return true;
}
return false;
}
// encode a blob for indexeddb engines that don't support blobs
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);
});
}
// decode an encoded blob
function _decodeBlob(encodedBlob) {
var arrayBuff = _binStringToArrayBuffer(atob(encodedBlob.data));
return createBlob([arrayBuff], { type: encodedBlob.type });
}
// is this one of our fancy encoded blobs?
function _isEncodedBlob(value) {
return value && value.__local_forage_encoded_blob;
}
// Specialize the default `ready()` function by making it dependent
// on the current database operations. Thus, the driver will be actually
// ready when it's been initialized (default) *and* there are no pending
// operations on the database (initiated by some other instances).
function _fullyReady(callback) {
var self = this;
var promise = self._initReady().then(function () {
var dbContext = dbContexts[self._dbInfo.name];
if (dbContext && dbContext.dbReady) {
return dbContext.dbReady;
}
});
executeTwoCallbacks(promise, callback, callback);
return promise;
}
// Try to establish a new db connection to replace the
// current one which is broken (i.e. experiencing
// InvalidStateError while creating a transaction).
function _tryReconnect(dbInfo) {
_deferReadiness(dbInfo);
var dbContext = dbContexts[dbInfo.name];
var forages = dbContext.forages;
for (var i = 0; i 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 string data storage.
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;
// OMG the serializations!
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) {
// Fill the string into a ArrayBuffer.
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 > 4;
bytes[p++] = (encoded2 & 15) > 2;
bytes[p++] = (encoded3 & 3) > 2];
base64String += BASE_CHARS[(bytes[i] & 3) > 4];
base64String += BASE_CHARS[(bytes[i + 1] & 15) > 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;
}
// Serialize a value, afterwards executing a callback (which usually
// instructs the `setItem()` callback/promise to be executed). This is how
// we store binary data with localStorage.
function serialize(value, callback) {
var valueType = '';
if (value) {
valueType = toString$1.call(value);
}
// Cannot use `value instanceof ArrayBuffer` or such here, as these
// checks fail when running the tests using casper.js...
//
// TODO: See why those tests fail and use a better solution.
if (value && (valueType === '[object ArrayBuffer]' || value.buffer && toString$1.call(value.buffer) === '[object ArrayBuffer]')) {
// Convert binary arrays to a string and prefix the string with
// a special marker.
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]') {
// Conver the blob to a binaryArray and then to a string.
var fileReader = new FileReader();
fileReader.onload = function () {
// Backwards-compatible prefix for the blob type.
var str = BLOB_TYPE_PREFIX + value.type + '~' + bufferToString(this.result);
callback(SERIALIZED_MARKER + TYPE_BLOB + str);
};
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);
}
}
}
// Deserialize data we've inserted into a value column/field. We place
// special markers into our strings to mark them as encoded; this isn't
// as nice as a meta field, but it's the only sane thing we can do whilst
// keeping localStorage support intact.
//
// Oftentimes this will just deserialize JSON content, but if we have a
// special marker (SERIALIZED_MARKER, defined above), we will extract
// some kind of arraybuffer/binary data/typed array out of the string.
function deserialize(value) {
// If we haven't marked this string as being specially serialized (i.e.
// something other than serialized JSON), we can just return it and be
// done with it.
if (value.substring(0, SERIALIZED_MARKER_LENGTH) !== SERIALIZED_MARKER) {
return JSON.parse(value);
}
// The following code deals with deserializing some kind of Blob or
// TypedArray. First we separate out the type of data we're dealing
// with from the data itself.
var serializedString = value.substring(TYPE_SERIALIZED_MARKER_LENGTH);
var type = value.substring(SERIALIZED_MARKER_LENGTH, TYPE_SERIALIZED_MARKER_LENGTH);
var blobType;
// Backwards-compatible blob type serialization strategy.
// DBs created with older versions of localForage will simply not have the blob type.
if (type === 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);
// Return the right type based on the code/type set during
// serialization.
switch (type) {
case TYPE_ARRAYBUFFER:
return buffer;
case TYPE_BLOB:
return createBlob([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: ' + type);
}
}
var localforageSerializer = {
serialize: serialize,
deserialize: deserialize,
stringToBuffer: stringToBuffer,
bufferToString: bufferToString
};
/*
* Includes code from:
*
* base64-arraybuffer
* https://github.com/niklasvh/base64-arraybuffer
*
* Copyright (c) 2012 Niklas von Hertzen
* Licensed under the MIT license.
*/
function createDbTable(t, dbInfo, callback, errorCallback) {
t.executeSql('CREATE TABLE IF NOT EXISTS ' + dbInfo.storeName + ' ' + '(id INTEGER PRIMARY KEY, key unique, value)', [], callback, errorCallback);
}
// Open the WebSQL database (automatically creates one if one didn't
// previously exist), using any options set in the config.
function _initStorage$1(options) {
var self = 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) {
// Open the database; the openDatabase API will automatically
// create it for us if it doesn't exist.
try {
dbInfo.db = openDatabase(dbInfo.name, String(dbInfo.version), dbInfo.description, dbInfo.size);
} catch (e) {
return reject(e);
}
// Create our key/value table if it doesn't exist.
dbInfo.db.transaction(function (t) {
createDbTable(t, dbInfo, function () {
self._dbInfo = dbInfo;
resolve();
}, function (t, error) {
reject(error);
});
}, reject);
});
dbInfo.serializer = localforageSerializer;
return dbInfoPromise;
}
function tryExecuteSql(t, dbInfo, sqlStatement, args, callback, errorCallback) {
t.executeSql(sqlStatement, args, callback, function (t, error) {
if (error.code === error.SYNTAX_ERR) {
t.executeSql('SELECT name FROM sqlite_master ' + "WHERE type='table' AND name = ?", [dbInfo.storeName], function (t, results) {
if (!results.rows.length) {
// if the table is missing (was deleted)
// re-create it table and retry
createDbTable(t, dbInfo, function () {
t.executeSql(sqlStatement, args, callback, errorCallback);
}, errorCallback);
} else {
errorCallback(t, error);
}
}, errorCallback);
} else {
errorCallback(t, error);
}
}, errorCallback);
}
function getItem$1(key, callback) {
var self = this;
key = normalizeKey(key);
var promise = new Promise$1(function (resolve, reject) {
self.ready().then(function () {
var dbInfo = self._dbInfo;
dbInfo.db.transaction(function (t) {
tryExecuteSql(t, dbInfo, 'SELECT * FROM ' + dbInfo.storeName + ' WHERE key = ? LIMIT 1', [key], function (t, results) {
var result = results.rows.length ? results.rows.item(0).value : null;
// Check to see if this is serialized content we need to
// unpack.
if (result) {
result = dbInfo.serializer.deserialize(result);
}
resolve(result);
}, function (t, error) {
reject(error);
});
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function iterate$1(iterator, callback) {
var self = this;
var promise = new Promise$1(function (resolve, reject) {
self.ready().then(function () {
var dbInfo = self._dbInfo;
dbInfo.db.transaction(function (t) {
tryExecuteSql(t, dbInfo, 'SELECT * FROM ' + dbInfo.storeName, [], function (t, results) {
var rows = results.rows;
var length = rows.length;
for (var i = 0; i 0) {
resolve(_setItem.apply(self, [key, originalValue, callback, retriesLeft - 1]));
return;
}
reject(sqlError);
}
});
}
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function setItem$1(key, value, callback) {
return _setItem.apply(this, [key, value, callback, 1]);
}
function removeItem$1(key, callback) {
var self = this;
key = normalizeKey(key);
var promise = new Promise$1(function (resolve, reject) {
self.ready().then(function () {
var dbInfo = self._dbInfo;
dbInfo.db.transaction(function (t) {
tryExecuteSql(t, dbInfo, 'DELETE FROM ' + dbInfo.storeName + ' WHERE key = ?', [key], function () {
resolve();
}, function (t, error) {
reject(error);
});
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
// Deletes every item in the table.
// TODO: Find out if this resets the AUTO_INCREMENT number.
function clear$1(callback) {
var self = this;
var promise = new Promise$1(function (resolve, reject) {
self.ready().then(function () {
var dbInfo = self._dbInfo;
dbInfo.db.transaction(function (t) {
tryExecuteSql(t, dbInfo, 'DELETE FROM ' + dbInfo.storeName, [], function () {
resolve();
}, function (t, error) {
reject(error);
});
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
// Does a simple `COUNT(key)` to get the number of items stored in
// localForage.
function length$1(callback) {
var self = this;
var promise = new Promise$1(function (resolve, reject) {
self.ready().then(function () {
var dbInfo = self._dbInfo;
dbInfo.db.transaction(function (t) {
// Ahhh, SQL makes this one soooooo easy.
tryExecuteSql(t, dbInfo, 'SELECT COUNT(key) as c FROM ' + dbInfo.storeName, [], function (t, results) {
var result = results.rows.item(0).c;
resolve(result);
}, function (t, error) {
reject(error);
});
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
// Return the key located at key index X; essentially gets the key from a
// `WHERE id = ?`. This is the most efficient way I can think to implement
// this rarely-used (in my experience) part of the API, but it can seem
// inconsistent, because we do `INSERT OR REPLACE INTO` on `setItem()`, so
// the ID of each key will change every time it's updated. Perhaps a stored
// procedure for the `setItem()` SQL would solve this problem?
// TODO: Don't change ID on `setItem()`.
function key$1(n, callback) {
var self = this;
var promise = new Promise$1(function (resolve, reject) {
self.ready().then(function () {
var dbInfo = self._dbInfo;
dbInfo.db.transaction(function (t) {
tryExecuteSql(t, dbInfo, 'SELECT key FROM ' + dbInfo.storeName + ' WHERE id = ? LIMIT 1', [n + 1], function (t, results) {
var result = results.rows.length ? results.rows.item(0).key : null;
resolve(result);
}, function (t, error) {
reject(error);
});
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function keys$1(callback) {
var self = this;
var promise = new Promise$1(function (resolve, reject) {
self.ready().then(function () {
var dbInfo = self._dbInfo;
dbInfo.db.transaction(function (t) {
tryExecuteSql(t, dbInfo, 'SELECT key FROM ' + dbInfo.storeName, [], function (t, results) {
var keys = [];
for (var i = 0; i There is no way to enumerate or delete the databases available for an origin from this API.
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 (t, results) {
var storeNames = [];
for (var i = 0; i 0;
}
// Config the localStorage backend, using options set in the config.
function _initStorage$2(options) {
var self = this;
var dbInfo = {};
if (options) {
for (var i in options) {
dbInfo[i] = options[i];
}
}
dbInfo.keyPrefix = _getKeyPrefix(options, self._defaultConfig);
if (!_isLocalStorageUsable()) {
return Promise$1.reject();
}
self._dbInfo = dbInfo;
dbInfo.serializer = localforageSerializer;
return Promise$1.resolve();
}
// Remove all keys from the datastore, effectively destroying all data in
// the app's key/value store!
function clear$2(callback) {
var self = this;
var promise = self.ready().then(function () {
var keyPrefix = self._dbInfo.keyPrefix;
for (var i = localStorage.length - 1; i >= 0; i--) {
var key = localStorage.key(i);
if (key.indexOf(keyPrefix) === 0) {
localStorage.removeItem(key);
}
}
});
executeCallback(promise, callback);
return promise;
}
// Retrieve an item from the store. Unlike the original async_storage
// library in Gaia, we don't modify return values at all. If a key's value
// is `undefined`, we pass that value to the callback function.
function getItem$2(key, callback) {
var self = this;
key = normalizeKey(key);
var promise = self.ready().then(function () {
var dbInfo = self._dbInfo;
var result = localStorage.getItem(dbInfo.keyPrefix + key);
// If a result was found, parse it from the serialized
// string into a JS object. If result isn't truthy, the key
// is likely undefined and we'll pass it straight to the
// callback.
if (result) {
result = dbInfo.serializer.deserialize(result);
}
return result;
});
executeCallback(promise, callback);
return promise;
}
// Iterate over all items in the store.
function iterate$2(iterator, callback) {
var self = this;
var promise = self.ready().then(function () {
var dbInfo = self._dbInfo;
var keyPrefix = dbInfo.keyPrefix;
var keyPrefixLength = keyPrefix.length;
var length = localStorage.length;
// We use a dedicated iterator instead of the `i` variable below
// so other keys we fetch in localStorage aren't counted in
// the `iterationNumber` argument passed to the `iterate()`
// callback.
//
// See: github.com/mozilla/localForage/pull/435#discussion_r38061530
var iterationNumber = 1;
for (var i = 0; i = 0; i--) {
var key = localStorage.key(i);
if (key.indexOf(keyPrefix) === 0) {
localStorage.removeItem(key);
}
}
});
}
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 sameValue(x, y) {
return x === y || typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y);
};
var includes = function includes(array, searchElement) {
var len = array.length;
var i = 0;
while (i b[0]) {
return +1;
} else {
return 0;
}
});
if (_this._entries) { // force reset because IE keeps keys index
_this._entries = {};
}
for (var i = 0; i 1) ? deserializeParam(attribute[1]) : ''
);
}
}
});
}
// HTMLAnchorElement
})(
(typeof global !== 'undefined') ? global
: ((typeof window !== 'undefined') ? window
: ((typeof self !== 'undefined') ? self : this))
);
(function(global) {
/**
* Polyfill URL
*
* Inspired from : https://github.com/arv/DOM-URL-Polyfill/blob/master/src/url.js
*/
var checkIfURLIsSupported = function() {
try {
var u = new global.URL('b', 'http://a');
u.pathname = 'c d';
return (u.href === 'http://a/c%20d') && u.searchParams;
} catch (e) {
return false;
}
};
var polyfillURL = function() {
var _URL = global.URL;
var URL = function(url, base) {
if (typeof url !== 'string') url = String(url);
// Only create another document if the base is different from current location.
var doc = document, baseElement;
if (base && (global.location === void 0 || base !== global.location.href)) {
doc = document.implementation.createHTMLDocument('');
baseElement = doc.createElement('base');
baseElement.href = base;
doc.head.appendChild(baseElement);
try {
if (baseElement.href.indexOf(base) !== 0) throw new Error(baseElement.href);
} catch (err) {
throw new Error('URL unable to set base ' + base + ' due to ' + err);
}
}
var anchorElement = doc.createElement('a');
anchorElement.href = url;
if (baseElement) {
doc.body.appendChild(anchorElement);
anchorElement.href = anchorElement.href; // force href to refresh
}
var inputElement = doc.createElement('input');
inputElement.type = 'url';
inputElement.value = url;
if (anchorElement.protocol === ':' || !/:/.test(anchorElement.href) || (!inputElement.checkValidity() && !base)) {
throw new TypeError('Invalid URL');
}
Object.defineProperty(this, '_anchorElement', {
value: anchorElement
});
// create a linked searchParams which reflect its changes on URL
var searchParams = new global.URLSearchParams(this.search);
var enableSearchUpdate = true;
var enableSearchParamsUpdate = true;
var _this = this;
['append', 'delete', 'set'].forEach(function(methodName) {
var method = searchParams[methodName];
searchParams[methodName] = function() {
method.apply(searchParams, arguments);
if (enableSearchUpdate) {
enableSearchParamsUpdate = false;
_this.search = searchParams.toString();
enableSearchParamsUpdate = true;
}
};
});
Object.defineProperty(this, 'searchParams', {
value: searchParams,
enumerable: true
});
var search = void 0;
Object.defineProperty(this, '_updateSearchParams', {
enumerable: false,
configurable: false,
writable: false,
value: function() {
if (this.search !== search) {
search = this.search;
if (enableSearchParamsUpdate) {
enableSearchUpdate = false;
this.searchParams._fromString(this.search);
enableSearchUpdate = true;
}
}
}
});
};
var proto = URL.prototype;
var linkURLWithAnchorAttribute = function(attributeName) {
Object.defineProperty(proto, attributeName, {
get: function() {
return this._anchorElement[attributeName];
},
set: function(value) {
this._anchorElement[attributeName] = value;
},
enumerable: true
});
};
['hash', 'host', 'hostname', 'port', 'protocol']
.forEach(function(attributeName) {
linkURLWithAnchorAttribute(attributeName);
});
Object.defineProperty(proto, 'search', {
get: function() {
return this._anchorElement['search'];
},
set: function(value) {
this._anchorElement['search'] = value;
this._updateSearchParams();
},
enumerable: true
});
Object.defineProperties(proto, {
'toString': {
get: function() {
var _this = this;
return function() {
return _this.href;
};
}
},
'href': {
get: function() {
return this._anchorElement.href.replace(/\?$/, '');
},
set: function(value) {
this._anchorElement.href = value;
this._updateSearchParams();
},
enumerable: true
},
'pathname': {
get: function() {
return this._anchorElement.pathname.replace(/(^\/?)/, '/');
},
set: function(value) {
this._anchorElement.pathname = value;
},
enumerable: true
},
'origin': {
get: function() {
// get expected port from protocol
var expectedPort = { 'http:': 80, 'https:': 443, 'ftp:': 21 }[this._anchorElement.protocol];
// add port to origin if, expected port is different than actual port
// and it is not empty f.e http://foo:8080
// 8080 != 80 && 8080 != ''
var addPortToOrigin = this._anchorElement.port != expectedPort &&
this._anchorElement.port !== '';
return this._anchorElement.protocol +
'//' +
this._anchorElement.hostname +
(addPortToOrigin ? (':' + this._anchorElement.port) : '');
},
enumerable: true
},
'password': { // TODO
get: function() {
return '';
},
set: function(value) {
},
enumerable: true
},
'username': { // TODO
get: function() {
return '';
},
set: function(value) {
},
enumerable: true
},
});
URL.createObjectURL = function(blob) {
return _URL.createObjectURL.apply(_URL, arguments);
};
URL.revokeObjectURL = function(url) {
return _URL.revokeObjectURL.apply(_URL, arguments);
};
global.URL = URL;
};
if (!checkIfURLIsSupported()) {
polyfillURL();
}
if ((global.location !== void 0) && !('origin' in global.location)) {
var getOrigin = function() {
return global.location.protocol + '//' + global.location.hostname + (global.location.port ? (':' + global.location.port) : '');
};
try {
Object.defineProperty(global.location, 'origin', {
get: getOrigin,
enumerable: true
});
} catch (e) {
setInterval(function() {
global.location.origin = getOrigin();
}, 100);
}
}
})(
(typeof global !== 'undefined') ? global
: ((typeof window !== 'undefined') ? window
: ((typeof self !== 'undefined') ? self : this))
);
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(5)))
/***/ })
/******/ ]);
});
//# sourceMappingURL=epub.js.map
/*!
JSZip v3.3.0 - A JavaScript class for generating and reading zip files
(c) 2009-2016 Stuart Knightley
Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown.
JSZip uses the library pako released under the MIT license :
https://github.com/nodeca/pako/blob/master/LICENSE
*/
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JSZip = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 2;
enc2 = ((chr1 & 3) > 4);
enc3 = remainingBytes > 1 ? (((chr2 & 15) > 6)) : 64;
enc4 = remainingBytes > 2 ? (chr3 & 63) : 64;
output.push(_keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4));
}
return output.join("");
};
// public method for decoding
exports.decode = function(input) {
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0, resultIndex = 0;
var dataUrlPrefix = "data:";
if (input.substr(0, dataUrlPrefix.length) === dataUrlPrefix) {
// This is a common error: people give a data url
// (data:image/png;base64,iVBOR...) with a {base64: true} and
// wonders why things don't work.
// We can detect that the string input looks like a data url but we
// *can't* be sure it is one: removing everything up to the comma would
// be too dangerous.
throw new Error("Invalid base64 input, it looks like a data url.");
}
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
var totalLength = input.length * 3 / 4;
if(input.charAt(input.length - 1) === _keyStr.charAt(64)) {
totalLength--;
}
if(input.charAt(input.length - 2) === _keyStr.charAt(64)) {
totalLength--;
}
if (totalLength % 1 !== 0) {
// totalLength is not an integer, the length does not match a valid
// base64 content. That can happen if:
// - the input is not a base64 content
// - the input is *almost* a base64 content, with a extra chars at the
// beginning or at the end
// - the input uses a base64 variant (base64url for example)
throw new Error("Invalid base64 input, bad content length.");
}
var output;
if (support.uint8array) {
output = new Uint8Array(totalLength|0);
} else {
output = new Array(totalLength|0);
}
while (i > 4);
chr2 = ((enc2 & 15) > 2);
chr3 = ((enc3 & 3) >> 1)) : (c >>> 1));
}
table[n] = c;
}
return table;
}
// Create table on load. Just 255 signed longs. Not a problem.
var crcTable = makeTable();
function crc32(crc, buf, len, pos) {
var t = crcTable, end = pos + len;
crc = crc ^ (-1);
for (var i = pos; i >> 8) ^ t[(crc ^ buf[i]) & 0xFF];
}
return (crc ^ (-1)); // >>> 0;
}
// That's all for the pako functions.
/**
* Compute the crc32 of a string.
* This is almost the same as the function crc32, but for strings. Using the
* same function for the two use cases leads to horrible performances.
* @param {Number} crc the starting value of the crc.
* @param {String} str the string to use.
* @param {Number} len the length of the string.
* @param {Number} pos the starting position for the crc32 computation.
* @return {Number} the computed crc32.
*/
function crc32str(crc, str, len, pos) {
var t = crcTable, end = pos + len;
crc = crc ^ (-1);
for (var i = pos; i >> 8) ^ t[(crc ^ str.charCodeAt(i)) & 0xFF];
}
return (crc ^ (-1)); // >>> 0;
}
module.exports = function crc32wrapper(input, crc) {
if (typeof input === "undefined" || !input.length) {
return 0;
}
var isArray = utils.getTypeOf(input) !== "string";
if(isArray) {
return crc32(crc|0, input, input.length, 0);
} else {
return crc32str(crc|0, input, input.length, 0);
}
};
},{"./utils":32}],5:[function(require,module,exports){
'use strict';
exports.base64 = false;
exports.binary = false;
exports.dir = false;
exports.createFolders = true;
exports.date = null;
exports.compression = null;
exports.compressionOptions = null;
exports.comment = null;
exports.unixPermissions = null;
exports.dosPermissions = null;
},{}],6:[function(require,module,exports){
/* global Promise */
'use strict';
// load the global object first:
// - it should be better integrated in the system (unhandledRejection in node)
// - the environment may have a custom Promise implementation (see zone.js)
var ES6Promise = null;
if (typeof Promise !== "undefined") {
ES6Promise = Promise;
} else {
ES6Promise = require("lie");
}
/**
* Let the user use/change some implementations.
*/
module.exports = {
Promise: ES6Promise
};
},{"lie":37}],7:[function(require,module,exports){
'use strict';
var USE_TYPEDARRAY = (typeof Uint8Array !== 'undefined') && (typeof Uint16Array !== 'undefined') && (typeof Uint32Array !== 'undefined');
var pako = require("pako");
var utils = require("./utils");
var GenericWorker = require("./stream/GenericWorker");
var ARRAY_TYPE = USE_TYPEDARRAY ? "uint8array" : "array";
exports.magic = "\x08\x00";
/**
* Create a worker that uses pako to inflate/deflate.
* @constructor
* @param {String} action the name of the pako function to call : either "Deflate" or "Inflate".
* @param {Object} options the options to use when (de)compressing.
*/
function FlateWorker(action, options) {
GenericWorker.call(this, "FlateWorker/" + action);
this._pako = null;
this._pakoAction = action;
this._pakoOptions = options;
// the `meta` object from the last chunk received
// this allow this worker to pass around metadata
this.meta = {};
}
utils.inherits(FlateWorker, GenericWorker);
/**
* @see GenericWorker.processChunk
*/
FlateWorker.prototype.processChunk = function (chunk) {
this.meta = chunk.meta;
if (this._pako === null) {
this._createPako();
}
this._pako.push(utils.transformTo(ARRAY_TYPE, chunk.data), false);
};
/**
* @see GenericWorker.flush
*/
FlateWorker.prototype.flush = function () {
GenericWorker.prototype.flush.call(this);
if (this._pako === null) {
this._createPako();
}
this._pako.push([], true);
};
/**
* @see GenericWorker.cleanUp
*/
FlateWorker.prototype.cleanUp = function () {
GenericWorker.prototype.cleanUp.call(this);
this._pako = null;
};
/**
* Create the _pako object.
* TODO: lazy-loading this object isn't the best solution but it's the
* quickest. The best solution is to lazy-load the worker list. See also the
* issue #446.
*/
FlateWorker.prototype._createPako = function () {
this._pako = new pako[this._pakoAction]({
raw: true,
level: this._pakoOptions.level || -1 // default compression
});
var self = this;
this._pako.onData = function(data) {
self.push({
data : data,
meta : self.meta
});
};
};
exports.compressWorker = function (compressionOptions) {
return new FlateWorker("Deflate", compressionOptions);
};
exports.uncompressWorker = function () {
return new FlateWorker("Inflate", {});
};
},{"./stream/GenericWorker":28,"./utils":32,"pako":38}],8:[function(require,module,exports){
'use strict';
var utils = require('../utils');
var GenericWorker = require('../stream/GenericWorker');
var utf8 = require('../utf8');
var crc32 = require('../crc32');
var signature = require('../signature');
/**
* Transform an integer into a string in hexadecimal.
* @private
* @param {number} dec the number to convert.
* @param {number} bytes the number of bytes to generate.
* @returns {string} the result.
*/
var decToHex = function(dec, bytes) {
var hex = "", i;
for (i = 0; i >> 8;
}
return hex;
};
/**
* Generate the UNIX part of the external file attributes.
* @param {Object} unixPermissions the unix permissions or null.
* @param {Boolean} isDir true if the entry is a directory, false otherwise.
* @return {Number} a 32 bit integer.
*
* adapted from http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute :
*
* TTTTsstrwxrwxrwx0000000000ADVSHR
* ^^^^____________________________ file type, see zipinfo.c (UNX_*)
* ^^^_________________________ setuid, setgid, sticky
* ^^^^^^^^^________________ permissions
* ^^^^^^^^^^______ not used ?
* ^^^^^^ DOS attribute bits : Archive, Directory, Volume label, System file, Hidden, Read only
*/
var generateUnixExternalFileAttr = function (unixPermissions, isDir) {
var result = unixPermissions;
if (!unixPermissions) {
// I can't use octal values in strict mode, hence the hexa.
// 040775 => 0x41fd
// 0100664 => 0x81b4
result = isDir ? 0x41fd : 0x81b4;
}
return (result & 0xFFFF) 0) ? path.substring(0, lastSlash) : "";
};
/**
* Returns the path with a slash at the end.
* @private
* @param {String} path the path to check.
* @return {String} the path with a trailing slash.
*/
var forceTrailingSlash = function(path) {
// Check the name ends with a /
if (path.slice(-1) !== "/") {
path += "/"; // IE doesn't like substr(-1)
}
return path;
};
/**
* Add a (sub) folder in the current folder.
* @private
* @param {string} name the folder's name
* @param {boolean=} [createFolders] If true, automatically create sub
* folders. Defaults to false.
* @return {Object} the new folder.
*/
var folderAdd = function(name, createFolders) {
createFolders = (typeof createFolders !== 'undefined') ? createFolders : defaults.createFolders;
name = forceTrailingSlash(name);
// Does this folder already exist?
if (!this.files[name]) {
fileAdd.call(this, name, null, {
dir: true,
createFolders: createFolders
});
}
return this.files[name];
};
/**
* Cross-window, cross-Node-context regular expression detection
* @param {Object} object Anything
* @return {Boolean} true if the object is a regular expression,
* false otherwise
*/
function isRegExp(object) {
return Object.prototype.toString.call(object) === "[object RegExp]";
}
// return the actual prototype of JSZip
var out = {
/**
* @see loadAsync
*/
load: function() {
throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide.");
},
/**
* Call a callback function for each entry at this folder level.
* @param {Function} cb the callback function:
* function (relativePath, file) {...}
* It takes 2 arguments : the relative path and the file.
*/
forEach: function(cb) {
var filename, relativePath, file;
for (filename in this.files) {
if (!this.files.hasOwnProperty(filename)) {
continue;
}
file = this.files[filename];
relativePath = filename.slice(this.root.length, filename.length);
if (relativePath && filename.slice(0, this.root.length) === this.root) { // the file is in the current root
cb(relativePath, file); // TODO reverse the parameters ? need to be clean AND consistent with the filter search fn...
}
}
},
/**
* Filter nested files/folders with the specified function.
* @param {Function} search the predicate to use :
* function (relativePath, file) {...}
* It takes 2 arguments : the relative path and the file.
* @return {Array} An array of matching elements.
*/
filter: function(search) {
var result = [];
this.forEach(function (relativePath, entry) {
if (search(relativePath, entry)) { // the file matches the function
result.push(entry);
}
});
return result;
},
/**
* Add a file to the zip file, or search a file.
* @param {string|RegExp} name The name of the file to add (if data is defined),
* the name of the file to find (if no data) or a regex to match files.
* @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded
* @param {Object} o File options
* @return {JSZip|Object|Array} this JSZip object (when adding a file),
* a file (when searching by string) or an array of files (when searching by regex).
*/
file: function(name, data, o) {
if (arguments.length === 1) {
if (isRegExp(name)) {
var regexp = name;
return this.filter(function(relativePath, file) {
return !file.dir && regexp.test(relativePath);
});
}
else { // text
var obj = this.files[this.root + name];
if (obj && !obj.dir) {
return obj;
} else {
return null;
}
}
}
else { // more than one argument : we have data !
name = this.root + name;
fileAdd.call(this, name, data, o);
}
return this;
},
/**
* Add a directory to the zip file, or search.
* @param {String|RegExp} arg The name of the directory to add, or a regex to search folders.
* @return {JSZip} an object with the new directory as the root, or an array containing matching folders.
*/
folder: function(arg) {
if (!arg) {
return this;
}
if (isRegExp(arg)) {
return this.filter(function(relativePath, file) {
return file.dir && arg.test(relativePath);
});
}
// else, name is a new folder
var name = this.root + arg;
var newFolder = folderAdd.call(this, name);
// Allow chaining by returning a new object with this folder as the root
var ret = this.clone();
ret.root = newFolder.name;
return ret;
},
/**
* Delete a file, or a directory and all sub-files, from the zip
* @param {string} name the name of the file to delete
* @return {JSZip} this JSZip object
*/
remove: function(name) {
name = this.root + name;
var file = this.files[name];
if (!file) {
// Look for any folders
if (name.slice(-1) !== "/") {
name += "/";
}
file = this.files[name];
}
if (file && !file.dir) {
// file
delete this.files[name];
} else {
// maybe a folder, delete recursively
var kids = this.filter(function(relativePath, file) {
return file.name.slice(0, name.length) === name;
});
for (var i = 0; i = 0; --i) {
if (this.data[i] === sig0 && this.data[i + 1] === sig1 && this.data[i + 2] === sig2 && this.data[i + 3] === sig3) {
return i - this.zero;
}
}
return -1;
};
/**
* @see DataReader.readAndCheckSignature
*/
ArrayReader.prototype.readAndCheckSignature = function (sig) {
var sig0 = sig.charCodeAt(0),
sig1 = sig.charCodeAt(1),
sig2 = sig.charCodeAt(2),
sig3 = sig.charCodeAt(3),
data = this.readData(4);
return sig0 === data[0] && sig1 === data[1] && sig2 === data[2] && sig3 === data[3];
};
/**
* @see DataReader.readData
*/
ArrayReader.prototype.readData = function(size) {
this.checkOffset(size);
if(size === 0) {
return [];
}
var result = this.data.slice(this.zero + this.index, this.zero + this.index + size);
this.index += size;
return result;
};
module.exports = ArrayReader;
},{"../utils":32,"./DataReader":18}],18:[function(require,module,exports){
'use strict';
var utils = require('../utils');
function DataReader(data) {
this.data = data; // type : see implementation
this.length = data.length;
this.index = 0;
this.zero = 0;
}
DataReader.prototype = {
/**
* Check that the offset will not go too far.
* @param {string} offset the additional offset to check.
* @throws {Error} an Error if the offset is out of bounds.
*/
checkOffset: function(offset) {
this.checkIndex(this.index + offset);
},
/**
* Check that the specified index will not be too far.
* @param {string} newIndex the index to check.
* @throws {Error} an Error if the index is out of bounds.
*/
checkIndex: function(newIndex) {
if (this.length = this.index; i--) {
result = (result bytes.
* @param {number} size the number of bytes to read.
* @return {Object} the raw data, implementation specific.
*/
readData: function(size) {
// see implementations
},
/**
* Find the last occurrence of a zip signature (4 bytes).
* @param {string} sig the signature to find.
* @return {number} the index of the last occurrence, -1 if not found.
*/
lastIndexOfSignature: function(sig) {
// see implementations
},
/**
* Read the signature (4 bytes) at the current position and compare it with sig.
* @param {string} sig the expected signature
* @return {boolean} true if the signature matches, false otherwise.
*/
readAndCheckSignature: function(sig) {
// see implementations
},
/**
* Get the next date.
* @return {Date} the date.
*/
readDate: function() {
var dostime = this.readInt(4);
return new Date(Date.UTC(
((dostime >> 25) & 0x7f) + 1980, // year
((dostime >> 21) & 0x0f) - 1, // month
(dostime >> 16) & 0x1f, // day
(dostime >> 11) & 0x1f, // hour
(dostime >> 5) & 0x3f, // minute
(dostime & 0x1f) = this.max) {
// EOF
return this.end();
} else {
switch(this.type) {
case "string":
data = this.data.substring(this.index, nextIndex);
break;
case "uint8array":
data = this.data.subarray(this.index, nextIndex);
break;
case "array":
case "nodebuffer":
data = this.data.slice(this.index, nextIndex);
break;
}
this.index = nextIndex;
return this.push({
data : data,
meta : {
percent : this.max ? this.index / this.max * 100 : 0
}
});
}
};
module.exports = DataWorker;
},{"../utils":32,"./GenericWorker":28}],28:[function(require,module,exports){
'use strict';
/**
* A worker that does nothing but passing chunks to the next one. This is like
* a nodejs stream but with some differences. On the good side :
* - it works on IE 6-9 without any issue / polyfill
* - it weights less than the full dependencies bundled with browserify
* - it forwards errors (no need to declare an error handler EVERYWHERE)
*
* A chunk is an object with 2 attributes : `meta` and `data`. The former is an
* object containing anything (`percent` for example), see each worker for more
* details. The latter is the real data (String, Uint8Array, etc).
*
* @constructor
* @param {String} name the name of the stream (mainly used for debugging purposes)
*/
function GenericWorker(name) {
// the name of the worker
this.name = name || "default";
// an object containing metadata about the workers chain
this.streamInfo = {};
// an error which happened when the worker was paused
this.generatedError = null;
// an object containing metadata to be merged by this worker into the general metadata
this.extraStreamInfo = {};
// true if the stream is paused (and should not do anything), false otherwise
this.isPaused = true;
// true if the stream is finished (and should not do anything), false otherwise
this.isFinished = false;
// true if the stream is locked to prevent further structure updates (pipe), false otherwise
this.isLocked = false;
// the event listeners
this._listeners = {
'data':[],
'end':[],
'error':[]
};
// the previous worker, if any
this.previous = null;
}
GenericWorker.prototype = {
/**
* Push a chunk to the next workers.
* @param {Object} chunk the chunk to push
*/
push : function (chunk) {
this.emit("data", chunk);
},
/**
* End the stream.
* @return {Boolean} true if this call ended the worker, false otherwise.
*/
end : function () {
if (this.isFinished) {
return false;
}
this.flush();
try {
this.emit("end");
this.cleanUp();
this.isFinished = true;
} catch (e) {
this.emit("error", e);
}
return true;
},
/**
* End the stream with an error.
* @param {Error} e the error which caused the premature end.
* @return {Boolean} true if this call ended the worker with an error, false otherwise.
*/
error : function (e) {
if (this.isFinished) {
return false;
}
if(this.isPaused) {
this.generatedError = e;
} else {
this.isFinished = true;
this.emit("error", e);
// in the workers chain exploded in the middle of the chain,
// the error event will go downward but we also need to notify
// workers upward that there has been an error.
if(this.previous) {
this.previous.error(e);
}
this.cleanUp();
}
return true;
},
/**
* Add a callback on an event.
* @param {String} name the name of the event (data, end, error)
* @param {Function} listener the function to call when the event is triggered
* @return {GenericWorker} the current object for chainability
*/
on : function (name, listener) {
this._listeners[name].push(listener);
return this;
},
/**
* Clean any references when a worker is ending.
*/
cleanUp : function () {
this.streamInfo = this.generatedError = this.extraStreamInfo = null;
this._listeners = [];
},
/**
* Trigger an event. This will call registered callback with the provided arg.
* @param {String} name the name of the event (data, end, error)
* @param {Object} arg the argument to call the callback with.
*/
emit : function (name, arg) {
if (this._listeners[name]) {
for(var i = 0; i " + me;
} else {
return me;
}
}
};
module.exports = GenericWorker;
},{}],29:[function(require,module,exports){
'use strict';
var utils = require('../utils');
var ConvertWorker = require('./ConvertWorker');
var GenericWorker = require('./GenericWorker');
var base64 = require('../base64');
var support = require("../support");
var external = require("../external");
var NodejsStreamOutputAdapter = null;
if (support.nodestream) {
try {
NodejsStreamOutputAdapter = require('../nodejs/NodejsStreamOutputAdapter');
} catch(e) {}
}
/**
* Apply the final transformation of the data. If the user wants a Blob for
* example, it's easier to work with an U8intArray and finally do the
* ArrayBuffer/Blob conversion.
* @param {String} type the name of the final type
* @param {String|Uint8Array|Buffer} content the content to transform
* @param {String} mimeType the mime type of the content, if applicable.
* @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the content in the right format.
*/
function transformZipOutput(type, content, mimeType) {
switch(type) {
case "blob" :
return utils.newBlob(utils.transformTo("arraybuffer", content), mimeType);
case "base64" :
return base64.encode(content);
default :
return utils.transformTo(type, content);
}
}
/**
* Concatenate an array of data of the given type.
* @param {String} type the type of the data in the given array.
* @param {Array} dataArray the array containing the data chunks to concatenate
* @return {String|Uint8Array|Buffer} the concatenated data
* @throws Error if the asked type is unsupported
*/
function concat (type, dataArray) {
var i, index = 0, res = null, totalLength = 0;
for(i = 0; i = 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1);
}
_utf8len[254]=_utf8len[254]=1; // Invalid sequence start
// convert string to array (typed, when possible)
var string2buf = function (str) {
var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;
// count binary size
for (m_pos = 0; m_pos >> 6);
buf[i++] = 0x80 | (c & 0x3f);
} else if (c >> 12);
buf[i++] = 0x80 | (c >>> 6 & 0x3f);
buf[i++] = 0x80 | (c & 0x3f);
} else {
/* four bytes */
buf[i++] = 0xf0 | (c >>> 18);
buf[i++] = 0x80 | (c >>> 12 & 0x3f);
buf[i++] = 0x80 | (c >>> 6 & 0x3f);
buf[i++] = 0x80 | (c & 0x3f);
}
}
return buf;
};
// Calculate max possible position in utf8 buffer,
// that will not break sequence. If that's not possible
// - (very small limits) return max size as is.
//
// buf[] - utf8 bytes array
// max - length limit (mandatory);
var utf8border = function(buf, max) {
var pos;
max = max || buf.length;
if (max > buf.length) { max = buf.length; }
// go back from last position, until start of sequence found
pos = max-1;
while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }
// Fuckup - very small and broken sequence,
// return max, because we should return something anyway.
if (pos max) ? pos : max;
};
// convert array to string
var buf2string = function (buf) {
var str, i, out, c, c_len;
var len = buf.length;
// Reserve max possible length (2 words per char)
// NB: by unknown reasons, Array is significantly faster for
// String.fromCharCode.apply than Uint16Array.
var utf16buf = new Array(len*2);
for (out=0, i=0; i 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; }
// apply mask on first byte
c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;
// join the rest
while (c_len > 1 && i 1) { utf16buf[out++] = 0xfffd; continue; }
if (c > 10) & 0x3ff);
utf16buf[out++] = 0xdc00 | (c & 0x3ff);
}
}
// shrinkBuf(utf16buf, out)
if (utf16buf.length !== out) {
if(utf16buf.subarray) {
utf16buf = utf16buf.subarray(0, out);
} else {
utf16buf.length = out;
}
}
// return String.fromCharCode.apply(null, utf16buf);
return utils.applyFromCharCode(utf16buf);
};
// That's all for the pako functions.
/**
* Transform a javascript string into an array (typed if possible) of bytes,
* UTF-8 encoded.
* @param {String} str the string to encode
* @return {Array|Uint8Array|Buffer} the UTF-8 encoded string.
*/
exports.utf8encode = function utf8encode(str) {
if (support.nodebuffer) {
return nodejsUtils.newBufferFrom(str, "utf-8");
}
return string2buf(str);
};
/**
* Transform a bytes array (or a representation) representing an UTF-8 encoded
* string into a javascript string.
* @param {Array|Uint8Array|Buffer} buf the data de decode
* @return {String} the decoded string.
*/
exports.utf8decode = function utf8decode(buf) {
if (support.nodebuffer) {
return utils.transformTo("nodebuffer", buf).toString("utf-8");
}
buf = utils.transformTo(support.uint8array ? "uint8array" : "array", buf);
return buf2string(buf);
};
/**
* A worker to decode utf8 encoded binary chunks into string chunks.
* @constructor
*/
function Utf8DecodeWorker() {
GenericWorker.call(this, "utf-8 decode");
// the last bytes if a chunk didn't end with a complete codepoint.
this.leftOver = null;
}
utils.inherits(Utf8DecodeWorker, GenericWorker);
/**
* @see GenericWorker.processChunk
*/
Utf8DecodeWorker.prototype.processChunk = function (chunk) {
var data = utils.transformTo(support.uint8array ? "uint8array" : "array", chunk.data);
// 1st step, re-use what's left of the previous chunk
if (this.leftOver && this.leftOver.length) {
if(support.uint8array) {
var previousData = data;
data = new Uint8Array(previousData.length + this.leftOver.length);
data.set(this.leftOver, 0);
data.set(previousData, this.leftOver.length);
} else {
data = this.leftOver.concat(data);
}
this.leftOver = null;
}
var nextBoundary = utf8border(data);
var usableData = data;
if (nextBoundary !== data.length) {
if (support.uint8array) {
usableData = data.subarray(0, nextBoundary);
this.leftOver = data.subarray(nextBoundary, data.length);
} else {
usableData = data.slice(0, nextBoundary);
this.leftOver = data.slice(nextBoundary, data.length);
}
}
this.push({
data : exports.utf8decode(usableData),
meta : chunk.meta
});
};
/**
* @see GenericWorker.flush
*/
Utf8DecodeWorker.prototype.flush = function () {
if(this.leftOver && this.leftOver.length) {
this.push({
data : exports.utf8decode(this.leftOver),
meta : {}
});
this.leftOver = null;
}
};
exports.Utf8DecodeWorker = Utf8DecodeWorker;
/**
* A worker to endcode string chunks into utf8 encoded binary chunks.
* @constructor
*/
function Utf8EncodeWorker() {
GenericWorker.call(this, "utf-8 encode");
}
utils.inherits(Utf8EncodeWorker, GenericWorker);
/**
* @see GenericWorker.processChunk
*/
Utf8EncodeWorker.prototype.processChunk = function (chunk) {
this.push({
data : exports.utf8encode(chunk.data),
meta : chunk.meta
});
};
exports.Utf8EncodeWorker = Utf8EncodeWorker;
},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(require,module,exports){
'use strict';
var support = require('./support');
var base64 = require('./base64');
var nodejsUtils = require('./nodejsUtils');
var setImmediate = require('set-immediate-shim');
var external = require("./external");
/**
* Convert a string that pass as a "binary string": it should represent a byte
* array but may have > 255 char codes. Be sure to take only the first byte
* and returns the byte array.
* @param {String} str the string to transform.
* @return {Array|Uint8Array} the string in a binary format.
*/
function string2binary(str) {
var result = null;
if (support.uint8array) {
result = new Uint8Array(str.length);
} else {
result = new Array(str.length);
}
return stringToArrayLike(str, result);
}
/**
* Create a new blob with the given content and the given type.
* @param {String|ArrayBuffer} part the content to put in the blob. DO NOT use
* an Uint8Array because the stock browser of android 4 won't accept it (it
* will be silently converted to a string, "[object Uint8Array]").
*
* Use only ONE part to build the blob to avoid a memory leak in IE11 / Edge:
* when a large amount of Array is used to create the Blob, the amount of
* memory consumed is nearly 100 times the original data amount.
*
* @param {String} type the mime type of the blob.
* @return {Blob} the created blob.
*/
exports.newBlob = function(part, type) {
exports.checkSupport("blob");
try {
// Blob constructor
return new Blob([part], {
type: type
});
}
catch (e) {
try {
// deprecated, browser only, old way
var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder;
var builder = new Builder();
builder.append(part);
return builder.getBlob(type);
}
catch (e) {
// well, fuck ?!
throw new Error("Bug : can't construct the Blob.");
}
}
};
/**
* The identity function.
* @param {Object} input the input.
* @return {Object} the same input.
*/
function identity(input) {
return input;
}
/**
* Fill in an array with a string.
* @param {String} str the string to use.
* @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated).
* @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array.
*/
function stringToArrayLike(str, array) {
for (var i = 0; i 1) {
try {
return arrayToStringHelper.stringifyByChunk(array, type, chunk);
} catch (e) {
chunk = Math.floor(chunk / 2);
}
}
}
// no apply or chunk error : slow and painful algorithm
// default browser on android 4.*
return arrayToStringHelper.stringifyByChar(array);
}
exports.applyFromCharCode = arrayLikeToString;
/**
* Copy the data from an array-like to an other array-like.
* @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array.
* @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated.
* @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array.
*/
function arrayLikeToArrayLike(arrayFrom, arrayTo) {
for (var i = 0; i 1) {
throw new Error("Multi-volumes zip are not supported");
}
},
/**
* Read the local files, based on the offset read in the central part.
*/
readLocalFiles: function() {
var i, file;
for (i = 0; i 0) {
// console.warn(extraBytes, "extra bytes at beginning or within zipfile");
if (this.isSignature(endOfCentralDirOffset, sig.CENTRAL_FILE_HEADER)) {
// The offsets seem wrong, but we have something at the specified offset.
// So… we keep it.
} else {
// the offset is wrong, update the "zero" of the reader
// this happens if data has been prepended (crx files for example)
this.reader.zero = extraBytes;
}
} else if (extraBytes > 8;
// Check if we have the DOS directory flag set.
// We look for it in the DOS and UNIX permissions
// but some unknown platform could set it as a compatibility flag.
this.dir = this.externalFileAttributes & 0x0010 ? true : false;
if(madeBy === MADE_BY_DOS) {
// first 6 bits (0 to 5)
this.dosPermissions = this.externalFileAttributes & 0x3F;
}
if(madeBy === MADE_BY_UNIX) {
this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF;
// the octal permissions are in (this.unixPermissions & 0x01FF).toString(8);
}
// fail safe : if the name ends with a / it probably means a folder
if (!this.dir && this.fileNameStr.slice(-1) === '/') {
this.dir = true;
}
},
/**
* Parse the ZIP64 extra field and merge the info in the current ZipEntry.
* @param {DataReader} reader the reader to use.
*/
parseZIP64ExtraField: function(reader) {
if (!this.extraFields[0x0001]) {
return;
}
// should be something, preparing the extra reader
var extraReader = readerFor(this.extraFields[0x0001].value);
// I really hope that these 64bits integer can fit in 32 bits integer, because js
// won't let us have more.
if (this.uncompressedSize === utils.MAX_VALUE_32BITS) {
this.uncompressedSize = extraReader.readInt(8);
}
if (this.compressedSize === utils.MAX_VALUE_32BITS) {
this.compressedSize = extraReader.readInt(8);
}
if (this.localHeaderOffset === utils.MAX_VALUE_32BITS) {
this.localHeaderOffset = extraReader.readInt(8);
}
if (this.diskNumberStart === utils.MAX_VALUE_32BITS) {
this.diskNumberStart = extraReader.readInt(4);
}
},
/**
* Read the central part of a zip file and add the info in this object.
* @param {DataReader} reader the reader to use.
*/
readExtraFields: function(reader) {
var end = reader.index + this.extraFieldsLength,
extraFieldId,
extraFieldLength,
extraFieldValue;
if (!this.extraFields) {
this.extraFields = {};
}
while (reader.index element; its readystatechange event will be fired asynchronously once it is inserted
// into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
var scriptEl = global.document.createElement('script');
scriptEl.onreadystatechange = function () {
nextTick();
scriptEl.onreadystatechange = null;
scriptEl.parentNode.removeChild(scriptEl);
scriptEl = null;
};
global.document.documentElement.appendChild(scriptEl);
};
} else {
scheduleDrain = function () {
setTimeout(nextTick, 0);
};
}
}
var draining;
var queue = [];
//named nextTick for less confusing stack traces
function nextTick() {
draining = true;
var i, oldQueue;
var len = queue.length;
while (len) {
oldQueue = queue;
queue = [];
i = -1;
while (++i Array
*
* Chunks of output data, if [[Deflate#onData]] not overriden.
**/
/**
* Deflate.result -> Uint8Array|Array
*
* Compressed result, generated by default [[Deflate#onData]]
* and [[Deflate#onEnd]] handlers. Filled after you push last chunk
* (call [[Deflate#push]] with `Z_FINISH` / `true` param) or if you
* push a chunk with explicit flush (call [[Deflate#push]] with
* `Z_SYNC_FLUSH` param).
**/
/**
* Deflate.err -> Number
*
* Error code after deflate finished. 0 (Z_OK) on success.
* You will not need it in real life, because deflate errors
* are possible only on wrong options or bad `onData` / `onEnd`
* custom handlers.
**/
/**
* Deflate.msg -> String
*
* Error message, if [[Deflate.err]] != 0
**/
/**
* new Deflate(options)
* - options (Object): zlib deflate options.
*
* Creates new deflator instance with specified params. Throws exception
* on bad params. Supported options:
*
* - `level`
* - `windowBits`
* - `memLevel`
* - `strategy`
* - `dictionary`
*
* [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
* for more information on these.
*
* Additional options, for internal needs:
*
* - `chunkSize` - size of generated data chunks (16K by default)
* - `raw` (Boolean) - do raw deflate
* - `gzip` (Boolean) - create gzip wrapper
* - `to` (String) - if equal to 'string', then result will be "binary string"
* (each char code [0..255])
* - `header` (Object) - custom header for gzip
* - `text` (Boolean) - true if compressed data believed to be text
* - `time` (Number) - modification time, unix timestamp
* - `os` (Number) - operation system code
* - `extra` (Array) - array of bytes with extra data (max 65536)
* - `name` (String) - file name (binary string)
* - `comment` (String) - comment (binary string)
* - `hcrc` (Boolean) - true if header crc should be added
*
* ##### Example:
*
* ```javascript
* var pako = require('pako')
* , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9])
* , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]);
*
* var deflate = new pako.Deflate({ level: 3});
*
* deflate.push(chunk1, false);
* deflate.push(chunk2, true); // true -> last chunk
*
* if (deflate.err) { throw new Error(deflate.err); }
*
* console.log(deflate.result);
* ```
**/
function Deflate(options) {
if (!(this instanceof Deflate)) return new Deflate(options);
this.options = utils.assign({
level: Z_DEFAULT_COMPRESSION,
method: Z_DEFLATED,
chunkSize: 16384,
windowBits: 15,
memLevel: 8,
strategy: Z_DEFAULT_STRATEGY,
to: ''
}, options || {});
var opt = this.options;
if (opt.raw && (opt.windowBits > 0)) {
opt.windowBits = -opt.windowBits;
}
else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits Boolean
* - data (Uint8Array|Array|ArrayBuffer|String): input data. Strings will be
* converted to utf8 byte sequence.
* - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.
* See constants. Skipped or `false` means Z_NO_FLUSH, `true` meansh Z_FINISH.
*
* Sends input data to deflate pipe, generating [[Deflate#onData]] calls with
* new compressed chunks. Returns `true` on success. The last data block must have
* mode Z_FINISH (or `true`). That will flush internal pending buffers and call
* [[Deflate#onEnd]]. For interim explicit flushes (without ending the stream) you
* can use mode Z_SYNC_FLUSH, keeping the compression context.
*
* On fail call [[Deflate#onEnd]] with error code and return false.
*
* We strongly recommend to use `Uint8Array` on input for best speed (output
* array format is detected automatically). Also, don't skip last param and always
* use the same type in your code (boolean or number). That will improve JS speed.
*
* For regular `Array`-s make sure all elements are [0..255].
*
* ##### Example
*
* ```javascript
* push(chunk, false); // push one of data chunks
* ...
* push(chunk, true); // push last chunk
* ```
**/
Deflate.prototype.push = function (data, mode) {
var strm = this.strm;
var chunkSize = this.options.chunkSize;
var status, _mode;
if (this.ended) { return false; }
_mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH);
// Convert data if needed
if (typeof data === 'string') {
// If we need to compress text, change encoding to utf8.
strm.input = strings.string2buf(data);
} else if (toString.call(data) === '[object ArrayBuffer]') {
strm.input = new Uint8Array(data);
} else {
strm.input = data;
}
strm.next_in = 0;
strm.avail_in = strm.input.length;
do {
if (strm.avail_out === 0) {
strm.output = new utils.Buf8(chunkSize);
strm.next_out = 0;
strm.avail_out = chunkSize;
}
status = zlib_deflate.deflate(strm, _mode); /* no bad return value */
if (status !== Z_STREAM_END && status !== Z_OK) {
this.onEnd(status);
this.ended = true;
return false;
}
if (strm.avail_out === 0 || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) {
if (this.options.to === 'string') {
this.onData(strings.buf2binstring(utils.shrinkBuf(strm.output, strm.next_out)));
} else {
this.onData(utils.shrinkBuf(strm.output, strm.next_out));
}
}
} while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END);
// Finalize on the last chunk.
if (_mode === Z_FINISH) {
status = zlib_deflate.deflateEnd(this.strm);
this.onEnd(status);
this.ended = true;
return status === Z_OK;
}
// callback interim results if Z_SYNC_FLUSH.
if (_mode === Z_SYNC_FLUSH) {
this.onEnd(Z_OK);
strm.avail_out = 0;
return true;
}
return true;
};
/**
* Deflate#onData(chunk) -> Void
* - chunk (Uint8Array|Array|String): ouput data. Type of array depends
* on js engine support. When string output requested, each chunk
* will be string.
*
* By default, stores data blocks in `chunks[]` property and glue
* those in `onEnd`. Override this handler, if you need another behaviour.
**/
Deflate.prototype.onData = function (chunk) {
this.chunks.push(chunk);
};
/**
* Deflate#onEnd(status) -> Void
* - status (Number): deflate status. 0 (Z_OK) on success,
* other if not.
*
* Called once after you tell deflate that the input stream is
* complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH)
* or if an error happened. By default - join collected chunks,
* free memory and fill `results` / `err` properties.
**/
Deflate.prototype.onEnd = function (status) {
// On success - join
if (status === Z_OK) {
if (this.options.to === 'string') {
this.result = this.chunks.join('');
} else {
this.result = utils.flattenChunks(this.chunks);
}
}
this.chunks = [];
this.err = status;
this.msg = this.strm.msg;
};
/**
* deflate(data[, options]) -> Uint8Array|Array|String
* - data (Uint8Array|Array|String): input data to compress.
* - options (Object): zlib deflate options.
*
* Compress `data` with deflate algorithm and `options`.
*
* Supported options are:
*
* - level
* - windowBits
* - memLevel
* - strategy
* - dictionary
*
* [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
* for more information on these.
*
* Sugar (options):
*
* - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify
* negative windowBits implicitly.
* - `to` (String) - if equal to 'string', then result will be "binary string"
* (each char code [0..255])
*
* ##### Example:
*
* ```javascript
* var pako = require('pako')
* , data = Uint8Array([1,2,3,4,5,6,7,8,9]);
*
* console.log(pako.deflate(data));
* ```
**/
function deflate(input, options) {
var deflator = new Deflate(options);
deflator.push(input, true);
// That will never happens, if you don't cheat with options :)
if (deflator.err) { throw deflator.msg || msg[deflator.err]; }
return deflator.result;
}
/**
* deflateRaw(data[, options]) -> Uint8Array|Array|String
* - data (Uint8Array|Array|String): input data to compress.
* - options (Object): zlib deflate options.
*
* The same as [[deflate]], but creates raw data, without wrapper
* (header and adler32 crc).
**/
function deflateRaw(input, options) {
options = options || {};
options.raw = true;
return deflate(input, options);
}
/**
* gzip(data[, options]) -> Uint8Array|Array|String
* - data (Uint8Array|Array|String): input data to compress.
* - options (Object): zlib deflate options.
*
* The same as [[deflate]], but create gzip wrapper instead of
* deflate one.
**/
function gzip(input, options) {
options = options || {};
options.gzip = true;
return deflate(input, options);
}
exports.Deflate = Deflate;
exports.deflate = deflate;
exports.deflateRaw = deflateRaw;
exports.gzip = gzip;
},{"./utils/common":41,"./utils/strings":42,"./zlib/deflate":46,"./zlib/messages":51,"./zlib/zstream":53}],40:[function(require,module,exports){
'use strict';
var zlib_inflate = require('./zlib/inflate');
var utils = require('./utils/common');
var strings = require('./utils/strings');
var c = require('./zlib/constants');
var msg = require('./zlib/messages');
var ZStream = require('./zlib/zstream');
var GZheader = require('./zlib/gzheader');
var toString = Object.prototype.toString;
/**
* class Inflate
*
* Generic JS-style wrapper for zlib calls. If you don't need
* streaming behaviour - use more simple functions: [[inflate]]
* and [[inflateRaw]].
**/
/* internal
* inflate.chunks -> Array
*
* Chunks of output data, if [[Inflate#onData]] not overriden.
**/
/**
* Inflate.result -> Uint8Array|Array|String
*
* Uncompressed result, generated by default [[Inflate#onData]]
* and [[Inflate#onEnd]] handlers. Filled after you push last chunk
* (call [[Inflate#push]] with `Z_FINISH` / `true` param) or if you
* push a chunk with explicit flush (call [[Inflate#push]] with
* `Z_SYNC_FLUSH` param).
**/
/**
* Inflate.err -> Number
*
* Error code after inflate finished. 0 (Z_OK) on success.
* Should be checked if broken data possible.
**/
/**
* Inflate.msg -> String
*
* Error message, if [[Inflate.err]] != 0
**/
/**
* new Inflate(options)
* - options (Object): zlib inflate options.
*
* Creates new inflator instance with specified params. Throws exception
* on bad params. Supported options:
*
* - `windowBits`
* - `dictionary`
*
* [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
* for more information on these.
*
* Additional options, for internal needs:
*
* - `chunkSize` - size of generated data chunks (16K by default)
* - `raw` (Boolean) - do raw inflate
* - `to` (String) - if equal to 'string', then result will be converted
* from utf8 to utf16 (javascript) string. When string output requested,
* chunk length can differ from `chunkSize`, depending on content.
*
* By default, when no options set, autodetect deflate/gzip data format via
* wrapper header.
*
* ##### Example:
*
* ```javascript
* var pako = require('pako')
* , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9])
* , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]);
*
* var inflate = new pako.Inflate({ level: 3});
*
* inflate.push(chunk1, false);
* inflate.push(chunk2, true); // true -> last chunk
*
* if (inflate.err) { throw new Error(inflate.err); }
*
* console.log(inflate.result);
* ```
**/
function Inflate(options) {
if (!(this instanceof Inflate)) return new Inflate(options);
this.options = utils.assign({
chunkSize: 16384,
windowBits: 0,
to: ''
}, options || {});
var opt = this.options;
// Force window size for `raw` data, if not set directly,
// because we have no header for autodetect.
if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits = 0) && (opt.windowBits 15) && (opt.windowBits gzipped data
// bit 4 (32) -> autodetect gzip/deflate
if ((opt.windowBits & 15) === 0) {
opt.windowBits |= 15;
}
}
this.err = 0; // error code, if happens (0 = Z_OK)
this.msg = ''; // error message
this.ended = false; // used to avoid multiple onEnd() calls
this.chunks = []; // chunks of compressed data
this.strm = new ZStream();
this.strm.avail_out = 0;
var status = zlib_inflate.inflateInit2(
this.strm,
opt.windowBits
);
if (status !== c.Z_OK) {
throw new Error(msg[status]);
}
this.header = new GZheader();
zlib_inflate.inflateGetHeader(this.strm, this.header);
}
/**
* Inflate#push(data[, mode]) -> Boolean
* - data (Uint8Array|Array|ArrayBuffer|String): input data
* - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.
* See constants. Skipped or `false` means Z_NO_FLUSH, `true` meansh Z_FINISH.
*
* Sends input data to inflate pipe, generating [[Inflate#onData]] calls with
* new output chunks. Returns `true` on success. The last data block must have
* mode Z_FINISH (or `true`). That will flush internal pending buffers and call
* [[Inflate#onEnd]]. For interim explicit flushes (without ending the stream) you
* can use mode Z_SYNC_FLUSH, keeping the decompression context.
*
* On fail call [[Inflate#onEnd]] with error code and return false.
*
* We strongly recommend to use `Uint8Array` on input for best speed (output
* format is detected automatically). Also, don't skip last param and always
* use the same type in your code (boolean or number). That will improve JS speed.
*
* For regular `Array`-s make sure all elements are [0..255].
*
* ##### Example
*
* ```javascript
* push(chunk, false); // push one of data chunks
* ...
* push(chunk, true); // push last chunk
* ```
**/
Inflate.prototype.push = function (data, mode) {
var strm = this.strm;
var chunkSize = this.options.chunkSize;
var dictionary = this.options.dictionary;
var status, _mode;
var next_out_utf8, tail, utf8str;
var dict;
// Flag to properly process Z_BUF_ERROR on testing inflate call
// when we check that all output data was flushed.
var allowBufError = false;
if (this.ended) { return false; }
_mode = (mode === ~~mode) ? mode : ((mode === true) ? c.Z_FINISH : c.Z_NO_FLUSH);
// Convert data if needed
if (typeof data === 'string') {
// Only binary strings can be decompressed on practice
strm.input = strings.binstring2buf(data);
} else if (toString.call(data) === '[object ArrayBuffer]') {
strm.input = new Uint8Array(data);
} else {
strm.input = data;
}
strm.next_in = 0;
strm.avail_in = strm.input.length;
do {
if (strm.avail_out === 0) {
strm.output = new utils.Buf8(chunkSize);
strm.next_out = 0;
strm.avail_out = chunkSize;
}
status = zlib_inflate.inflate(strm, c.Z_NO_FLUSH); /* no bad return value */
if (status === c.Z_NEED_DICT && dictionary) {
// Convert data if needed
if (typeof dictionary === 'string') {
dict = strings.string2buf(dictionary);
} else if (toString.call(dictionary) === '[object ArrayBuffer]') {
dict = new Uint8Array(dictionary);
} else {
dict = dictionary;
}
status = zlib_inflate.inflateSetDictionary(this.strm, dict);
}
if (status === c.Z_BUF_ERROR && allowBufError === true) {
status = c.Z_OK;
allowBufError = false;
}
if (status !== c.Z_STREAM_END && status !== c.Z_OK) {
this.onEnd(status);
this.ended = true;
return false;
}
if (strm.next_out) {
if (strm.avail_out === 0 || status === c.Z_STREAM_END || (strm.avail_in === 0 && (_mode === c.Z_FINISH || _mode === c.Z_SYNC_FLUSH))) {
if (this.options.to === 'string') {
next_out_utf8 = strings.utf8border(strm.output, strm.next_out);
tail = strm.next_out - next_out_utf8;
utf8str = strings.buf2string(strm.output, next_out_utf8);
// move tail
strm.next_out = tail;
strm.avail_out = chunkSize - tail;
if (tail) { utils.arraySet(strm.output, strm.output, next_out_utf8, tail, 0); }
this.onData(utf8str);
} else {
this.onData(utils.shrinkBuf(strm.output, strm.next_out));
}
}
}
// When no more input data, we should check that internal inflate buffers
// are flushed. The only way to do it when avail_out = 0 - run one more
// inflate pass. But if output data not exists, inflate return Z_BUF_ERROR.
// Here we set flag to process this error properly.
//
// NOTE. Deflate does not return error in this case and does not needs such
// logic.
if (strm.avail_in === 0 && strm.avail_out === 0) {
allowBufError = true;
}
} while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== c.Z_STREAM_END);
if (status === c.Z_STREAM_END) {
_mode = c.Z_FINISH;
}
// Finalize on the last chunk.
if (_mode === c.Z_FINISH) {
status = zlib_inflate.inflateEnd(this.strm);
this.onEnd(status);
this.ended = true;
return status === c.Z_OK;
}
// callback interim results if Z_SYNC_FLUSH.
if (_mode === c.Z_SYNC_FLUSH) {
this.onEnd(c.Z_OK);
strm.avail_out = 0;
return true;
}
return true;
};
/**
* Inflate#onData(chunk) -> Void
* - chunk (Uint8Array|Array|String): ouput data. Type of array depends
* on js engine support. When string output requested, each chunk
* will be string.
*
* By default, stores data blocks in `chunks[]` property and glue
* those in `onEnd`. Override this handler, if you need another behaviour.
**/
Inflate.prototype.onData = function (chunk) {
this.chunks.push(chunk);
};
/**
* Inflate#onEnd(status) -> Void
* - status (Number): inflate status. 0 (Z_OK) on success,
* other if not.
*
* Called either after you tell inflate that the input stream is
* complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH)
* or if an error happened. By default - join collected chunks,
* free memory and fill `results` / `err` properties.
**/
Inflate.prototype.onEnd = function (status) {
// On success - join
if (status === c.Z_OK) {
if (this.options.to === 'string') {
// Glue & convert here, until we teach pako to send
// utf8 alligned strings to onData
this.result = this.chunks.join('');
} else {
this.result = utils.flattenChunks(this.chunks);
}
}
this.chunks = [];
this.err = status;
this.msg = this.strm.msg;
};
/**
* inflate(data[, options]) -> Uint8Array|Array|String
* - data (Uint8Array|Array|String): input data to decompress.
* - options (Object): zlib inflate options.
*
* Decompress `data` with inflate/ungzip and `options`. Autodetect
* format via wrapper header by default. That's why we don't provide
* separate `ungzip` method.
*
* Supported options are:
*
* - windowBits
*
* [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
* for more information.
*
* Sugar (options):
*
* - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify
* negative windowBits implicitly.
* - `to` (String) - if equal to 'string', then result will be converted
* from utf8 to utf16 (javascript) string. When string output requested,
* chunk length can differ from `chunkSize`, depending on content.
*
*
* ##### Example:
*
* ```javascript
* var pako = require('pako')
* , input = pako.deflate([1,2,3,4,5,6,7,8,9])
* , output;
*
* try {
* output = pako.inflate(input);
* } catch (err)
* console.log(err);
* }
* ```
**/
function inflate(input, options) {
var inflator = new Inflate(options);
inflator.push(input, true);
// That will never happens, if you don't cheat with options :)
if (inflator.err) { throw inflator.msg || msg[inflator.err]; }
return inflator.result;
}
/**
* inflateRaw(data[, options]) -> Uint8Array|Array|String
* - data (Uint8Array|Array|String): input data to decompress.
* - options (Object): zlib inflate options.
*
* The same as [[inflate]], but creates raw data, without wrapper
* (header and adler32 crc).
**/
function inflateRaw(input, options) {
options = options || {};
options.raw = true;
return inflate(input, options);
}
/**
* ungzip(data[, options]) -> Uint8Array|Array|String
* - data (Uint8Array|Array|String): input data to decompress.
* - options (Object): zlib inflate options.
*
* Just shortcut to [[inflate]], because it autodetects format
* by header.content. Done for convenience.
**/
exports.Inflate = Inflate;
exports.inflate = inflate;
exports.inflateRaw = inflateRaw;
exports.ungzip = inflate;
},{"./utils/common":41,"./utils/strings":42,"./zlib/constants":44,"./zlib/gzheader":47,"./zlib/inflate":49,"./zlib/messages":51,"./zlib/zstream":53}],41:[function(require,module,exports){
'use strict';
var TYPED_OK = (typeof Uint8Array !== 'undefined') &&
(typeof Uint16Array !== 'undefined') &&
(typeof Int32Array !== 'undefined');
exports.assign = function (obj /*from1, from2, from3, ...*/) {
var sources = Array.prototype.slice.call(arguments, 1);
while (sources.length) {
var source = sources.shift();
if (!source) { continue; }
if (typeof source !== 'object') {
throw new TypeError(source + 'must be non-object');
}
for (var p in source) {
if (source.hasOwnProperty(p)) {
obj[p] = source[p];
}
}
}
return obj;
};
// reduce buffer size, avoiding mem copy
exports.shrinkBuf = function (buf, size) {
if (buf.length === size) { return buf; }
if (buf.subarray) { return buf.subarray(0, size); }
buf.length = size;
return buf;
};
var fnTyped = {
arraySet: function (dest, src, src_offs, len, dest_offs) {
if (src.subarray && dest.subarray) {
dest.set(src.subarray(src_offs, src_offs + len), dest_offs);
return;
}
// Fallback to ordinary array
for (var i = 0; i = 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1);
}
_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start
// convert string to array (typed, when possible)
exports.string2buf = function (str) {
var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;
// count binary size
for (m_pos = 0; m_pos >> 6);
buf[i++] = 0x80 | (c & 0x3f);
} else if (c >> 12);
buf[i++] = 0x80 | (c >>> 6 & 0x3f);
buf[i++] = 0x80 | (c & 0x3f);
} else {
/* four bytes */
buf[i++] = 0xf0 | (c >>> 18);
buf[i++] = 0x80 | (c >>> 12 & 0x3f);
buf[i++] = 0x80 | (c >>> 6 & 0x3f);
buf[i++] = 0x80 | (c & 0x3f);
}
}
return buf;
};
// Helper (used in 2 places)
function buf2binstring(buf, len) {
// use fallback for big arrays to avoid stack overflow
if (len 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; }
// apply mask on first byte
c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;
// join the rest
while (c_len > 1 && i 1) { utf16buf[out++] = 0xfffd; continue; }
if (c > 10) & 0x3ff);
utf16buf[out++] = 0xdc00 | (c & 0x3ff);
}
}
return buf2binstring(utf16buf, out);
};
// Calculate max possible position in utf8 buffer,
// that will not break sequence. If that's not possible
// - (very small limits) return max size as is.
//
// buf[] - utf8 bytes array
// max - length limit (mandatory);
exports.utf8border = function (buf, max) {
var pos;
max = max || buf.length;
if (max > buf.length) { max = buf.length; }
// go back from last position, until start of sequence found
pos = max - 1;
while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }
// Fuckup - very small and broken sequence,
// return max, because we should return something anyway.
if (pos max) ? pos : max;
};
},{"./common":41}],43:[function(require,module,exports){
'use strict';
// Note: adler32 takes 12% for level 0 and 2% for level 6.
// It doesn't worth to make additional optimizationa as in original.
// Small size is preferable.
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
function adler32(adler, buf, len, pos) {
var s1 = (adler & 0xffff) |0,
s2 = ((adler >>> 16) & 0xffff) |0,
n = 0;
while (len !== 0) {
// Set limit ~ twice less than 5552, to keep
// s2 in 31-bits, because we force signed ints.
// in other case %= will fail.
n = len > 2000 ? 2000 : len;
len -= n;
do {
s1 = (s1 + buf[pos++]) |0;
s2 = (s2 + s1) |0;
} while (--n);
s1 %= 65521;
s2 %= 65521;
}
return (s1 | (s2 >> 1)) : (c >>> 1));
}
table[n] = c;
}
return table;
}
// Create table on load. Just 255 signed longs. Not a problem.
var crcTable = makeTable();
function crc32(crc, buf, len, pos) {
var t = crcTable,
end = pos + len;
crc ^= -1;
for (var i = pos; i >> 8) ^ t[(crc ^ buf[i]) & 0xFF];
}
return (crc ^ (-1)); // >>> 0;
}
module.exports = crc32;
},{}],46:[function(require,module,exports){
'use strict';
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
var utils = require('../utils/common');
var trees = require('./trees');
var adler32 = require('./adler32');
var crc32 = require('./crc32');
var msg = require('./messages');
/* Public constants ==========================================================*/
/* ===========================================================================*/
/* Allowed flush values; see deflate() and inflate() below for details */
var Z_NO_FLUSH = 0;
var Z_PARTIAL_FLUSH = 1;
//var Z_SYNC_FLUSH = 2;
var Z_FULL_FLUSH = 3;
var Z_FINISH = 4;
var Z_BLOCK = 5;
//var Z_TREES = 6;
/* Return codes for the compression/decompression functions. Negative values
* are errors, positive values are used for special but normal events.
*/
var Z_OK = 0;
var Z_STREAM_END = 1;
//var Z_NEED_DICT = 2;
//var Z_ERRNO = -1;
var Z_STREAM_ERROR = -2;
var Z_DATA_ERROR = -3;
//var Z_MEM_ERROR = -4;
var Z_BUF_ERROR = -5;
//var Z_VERSION_ERROR = -6;
/* compression levels */
//var Z_NO_COMPRESSION = 0;
//var Z_BEST_SPEED = 1;
//var Z_BEST_COMPRESSION = 9;
var Z_DEFAULT_COMPRESSION = -1;
var Z_FILTERED = 1;
var Z_HUFFMAN_ONLY = 2;
var Z_RLE = 3;
var Z_FIXED = 4;
var Z_DEFAULT_STRATEGY = 0;
/* Possible values of the data_type field (though see inflate()) */
//var Z_BINARY = 0;
//var Z_TEXT = 1;
//var Z_ASCII = 1; // = Z_TEXT
var Z_UNKNOWN = 2;
/* The deflate compression method */
var Z_DEFLATED = 8;
/*============================================================================*/
var MAX_MEM_LEVEL = 9;
/* Maximum value for memLevel in deflateInit2 */
var MAX_WBITS = 15;
/* 32K LZ77 window */
var DEF_MEM_LEVEL = 8;
var LENGTH_CODES = 29;
/* number of length codes, not counting the special END_BLOCK code */
var LITERALS = 256;
/* number of literal bytes 0..255 */
var L_CODES = LITERALS + 1 + LENGTH_CODES;
/* number of Literal or Length codes, including the END_BLOCK code */
var D_CODES = 30;
/* number of distance codes */
var BL_CODES = 19;
/* number of codes used to transfer the bit lengths */
var HEAP_SIZE = 2 * L_CODES + 1;
/* maximum heap size */
var MAX_BITS = 15;
/* All codes must not exceed MAX_BITS bits */
var MIN_MATCH = 3;
var MAX_MATCH = 258;
var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
var PRESET_DICT = 0x20;
var INIT_STATE = 42;
var EXTRA_STATE = 69;
var NAME_STATE = 73;
var COMMENT_STATE = 91;
var HCRC_STATE = 103;
var BUSY_STATE = 113;
var FINISH_STATE = 666;
var BS_NEED_MORE = 1; /* block not completed, need more input or more output */
var BS_BLOCK_DONE = 2; /* block flush performed */
var BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */
var BS_FINISH_DONE = 4; /* finish done, accept no more input or output */
var OS_CODE = 0x03; // Unix :) . Don't detect, use this default.
function err(strm, errorCode) {
strm.msg = msg[errorCode];
return errorCode;
}
function rank(f) {
return ((f) 4 ? 9 : 0);
}
function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } }
/* =========================================================================
* Flush as much pending output as possible. All deflate() output goes
* through this function so some applications may wish to modify it
* to avoid allocating a large strm->output buffer and copying into it.
* (See also read_buf()).
*/
function flush_pending(strm) {
var s = strm.state;
//_tr_flush_bits(s);
var len = s.pending;
if (len > strm.avail_out) {
len = strm.avail_out;
}
if (len === 0) { return; }
utils.arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out);
strm.next_out += len;
s.pending_out += len;
strm.total_out += len;
strm.avail_out -= len;
s.pending -= len;
if (s.pending === 0) {
s.pending_out = 0;
}
}
function flush_block_only(s, last) {
trees._tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last);
s.block_start = s.strstart;
flush_pending(s.strm);
}
function put_byte(s, b) {
s.pending_buf[s.pending++] = b;
}
/* =========================================================================
* Put a short in the pending buffer. The 16-bit value is put in MSB order.
* IN assertion: the stream state is correct and there is enough room in
* pending_buf.
*/
function putShortMSB(s, b) {
// put_byte(s, (Byte)(b >> 8));
// put_byte(s, (Byte)(b & 0xff));
s.pending_buf[s.pending++] = (b >>> 8) & 0xff;
s.pending_buf[s.pending++] = b & 0xff;
}
/* ===========================================================================
* Read a new buffer from the current input stream, update the adler32
* and total number of bytes read. All deflate() input goes through
* this function so some applications may wish to modify it to avoid
* allocating a large strm->input buffer and copying from it.
* (See also flush_pending()).
*/
function read_buf(strm, buf, start, size) {
var len = strm.avail_in;
if (len > size) { len = size; }
if (len === 0) { return 0; }
strm.avail_in -= len;
// zmemcpy(buf, strm->next_in, len);
utils.arraySet(buf, strm.input, strm.next_in, len, start);
if (strm.state.wrap === 1) {
strm.adler = adler32(strm.adler, buf, len, start);
}
else if (strm.state.wrap === 2) {
strm.adler = crc32(strm.adler, buf, len, start);
}
strm.next_in += len;
strm.total_in += len;
return len;
}
/* ===========================================================================
* Set match_start to the longest match starting at the given string and
* return its length. Matches shorter or equal to prev_length are discarded,
* in which case the result is equal to prev_length and match_start is
* garbage.
* IN assertions: cur_match is the head of the hash chain for the current
* string (strstart) and its distance is = 1
* OUT assertion: the match length is not greater than s->lookahead.
*/
function longest_match(s, cur_match) {
var chain_length = s.max_chain_length; /* max hash chain length */
var scan = s.strstart; /* current string */
var match; /* matched string */
var len; /* length of current match */
var best_len = s.prev_length; /* best match length so far */
var nice_match = s.nice_match; /* stop if match long enough */
var limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ?
s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/;
var _win = s.window; // shortcut
var wmask = s.w_mask;
var prev = s.prev;
/* Stop when cur_match becomes = 8 and MAX_MATCH-2 multiple of 16.
* It is easy to get rid of this optimization if necessary.
*/
// Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
/* Do not waste too much time if we already have a good match: */
if (s.prev_length >= s.good_match) {
chain_length >>= 2;
}
/* Do not look for matches beyond the end of the input. This is necessary
* to make deflate deterministic.
*/
if (nice_match > s.lookahead) { nice_match = s.lookahead; }
// Assert((ulg)s->strstart window_size-MIN_LOOKAHEAD, "need lookahead");
do {
// Assert(cur_match strstart, "no future");
match = cur_match;
/* Skip to next match if the match length cannot increase
* or if the match length is less than 2. Note that the checks below
* for insufficient lookahead only occur occasionally for performance
* reasons. Therefore uninitialized memory will be accessed, and
* conditional jumps will be made that depend on those values.
* However the length of the match is limited to the lookahead, so
* the output of deflate is not affected by the uninitialized values.
*/
if (_win[match + best_len] !== scan_end ||
_win[match + best_len - 1] !== scan_end1 ||
_win[match] !== _win[scan] ||
_win[++match] !== _win[scan + 1]) {
continue;
}
/* The check at best_len-1 can be removed because it will be made
* again later. (This heuristic is not always a win.)
* It is not necessary to compare scan[2] and match[2] since they
* are always equal when the other bytes match, given that
* the hash keys are equal and that HASH_BITS >= 8.
*/
scan += 2;
match++;
// Assert(*scan == *match, "match[2]?");
/* We check for insufficient lookahead only every 8th comparison;
* the 256th check will be made at strstart+258.
*/
do {
/*jshint noempty:false*/
} while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
scan window+(unsigned)(s->window_size-1), "wild scan");
len = MAX_MATCH - (strend - scan);
scan = strend - MAX_MATCH;
if (len > best_len) {
s.match_start = cur_match;
best_len = len;
if (len >= nice_match) {
break;
}
scan_end1 = _win[scan + best_len - 1];
scan_end = _win[scan + best_len];
}
} while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0);
if (best_len lookahead strstart == 0 && s->lookahead == 0) {
// more = wsize;
//
// } else if (more == (unsigned)(-1)) {
// /* Very unlikely, but possible on 16 bit machine if
// * strstart == 0 && lookahead == 1 (input done a byte at time)
// */
// more--;
// }
//}
/* If the window is almost full and there is insufficient lookahead,
* move the upper half to the lower one to make room in the upper half.
*/
if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) {
utils.arraySet(s.window, s.window, _w_size, _w_size, 0);
s.match_start -= _w_size;
s.strstart -= _w_size;
/* we now have strstart >= MAX_DIST */
s.block_start -= _w_size;
/* Slide the hash table (could be avoided with 32 bit values
at the expense of memory usage). We slide even when level == 0
to keep the hash table consistent if we switch back to level > 0
later. (Using level 0 permanently is not an optimal usage of
zlib, so we don't care about this pathological case.)
*/
n = s.hash_size;
p = n;
do {
m = s.head[--p];
s.head[p] = (m >= _w_size ? m - _w_size : 0);
} while (--n);
n = _w_size;
p = n;
do {
m = s.prev[--p];
s.prev[p] = (m >= _w_size ? m - _w_size : 0);
/* If n is not on any hash chain, prev[n] is garbage but
* its value will never be used.
*/
} while (--n);
more += _w_size;
}
if (s.strm.avail_in === 0) {
break;
}
/* If there was no sliding:
* strstart more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
* => more >= window_size - 2*WSIZE + 2
* In the BIG_MEM or MMAP case (not yet supported),
* window_size == input_size + MIN_LOOKAHEAD &&
* strstart + s->lookahead more >= MIN_LOOKAHEAD.
* Otherwise, window_size == 2*WSIZE so more >= 2.
* If there was sliding, more >= WSIZE. So in all cases, more >= 2.
*/
//Assert(more >= 2, "more = MIN_MATCH) {
str = s.strstart - s.insert;
s.ins_h = s.window[str];
/* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */
s.ins_h = ((s.ins_h ins_h, s->window[str + MIN_MATCH-1]); */
s.ins_h = ((s.ins_h WIN_INIT)
// init = WIN_INIT;
// zmemzero(s->window + curr, (unsigned)init);
// s->high_water = curr + init;
// }
// else if (s->high_water high_water;
// if (init > s->window_size - s->high_water)
// init = s->window_size - s->high_water;
// zmemzero(s->window + s->high_water, (unsigned)init);
// s->high_water += init;
// }
// }
//
// Assert((ulg)s->strstart window_size - MIN_LOOKAHEAD,
// "not enough room for search");
}
/* ===========================================================================
* Copy without compression as much as possible from the input stream, return
* the current block state.
* This function does not insert new strings in the dictionary since
* uncompressible data is probably not useful. This function is used
* only for the level=0 compression option.
* NOTE: this function should be optimized to avoid extra copying from
* window to pending_buf.
*/
function deflate_stored(s, flush) {
/* Stored blocks are limited to 0xffff bytes, pending_buf is limited
* to pending_buf_size, and each stored block has a 5 byte header:
*/
var max_block_size = 0xffff;
if (max_block_size > s.pending_buf_size - 5) {
max_block_size = s.pending_buf_size - 5;
}
/* Copy as much as possible from input to output: */
for (;;) {
/* Fill the window as much as possible: */
if (s.lookahead strstart w_size+MAX_DIST(s) ||
// s->block_start >= (long)s->w_size, "slide too late");
// if (!(s.strstart = s.w_size)) {
// throw new Error("slide too late");
// }
fill_window(s);
if (s.lookahead === 0 && flush === Z_NO_FLUSH) {
return BS_NEED_MORE;
}
if (s.lookahead === 0) {
break;
}
/* flush the current block */
}
//Assert(s->block_start >= 0L, "block gone");
// if (s.block_start = max_start) {
/* strstart == 0 is possible when wraparound on 16-bit machine */
s.lookahead = s.strstart - max_start;
s.strstart = max_start;
/*** FLUSH_BLOCK(s, 0); ***/
flush_block_only(s, false);
if (s.strm.avail_out === 0) {
return BS_NEED_MORE;
}
/***/
}
/* Flush if we may have to slide, otherwise block_start may become
* negative and the data will be gone:
*/
if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) {
/*** FLUSH_BLOCK(s, 0); ***/
flush_block_only(s, false);
if (s.strm.avail_out === 0) {
return BS_NEED_MORE;
}
/***/
}
}
s.insert = 0;
if (flush === Z_FINISH) {
/*** FLUSH_BLOCK(s, 1); ***/
flush_block_only(s, true);
if (s.strm.avail_out === 0) {
return BS_FINISH_STARTED;
}
/***/
return BS_FINISH_DONE;
}
if (s.strstart > s.block_start) {
/*** FLUSH_BLOCK(s, 0); ***/
flush_block_only(s, false);
if (s.strm.avail_out === 0) {
return BS_NEED_MORE;
}
/***/
}
return BS_NEED_MORE;
}
/* ===========================================================================
* Compress as much as possible from the input stream, return the current
* block state.
* This function does not perform lazy evaluation of matches and inserts
* new strings in the dictionary only for unmatched strings or for short
* matches. It is used only for the fast compression options.
*/
function deflate_fast(s, flush) {
var hash_head; /* head of the hash chain */
var bflush; /* set if current block must be flushed */
for (;;) {
/* Make sure that we always have enough lookahead, except
* at the end of the input file. We need MAX_MATCH bytes
* for the next match, plus MIN_MATCH bytes to insert the
* string following the next match.
*/
if (s.lookahead = MIN_MATCH) {
/*** INSERT_STRING(s, s.strstart, hash_head); ***/
s.ins_h = ((s.ins_h = MIN_MATCH) {
// check_match(s, s.strstart, s.match_start, s.match_length); // for debug only
/*** _tr_tally_dist(s, s.strstart - s.match_start,
s.match_length - MIN_MATCH, bflush); ***/
bflush = trees._tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH);
s.lookahead -= s.match_length;
/* Insert new strings in the hash table only if the match length
* is not too large. This saves time but degrades compression.
*/
if (s.match_length = MIN_MATCH) {
s.match_length--; /* string at strstart already in table */
do {
s.strstart++;
/*** INSERT_STRING(s, s.strstart, hash_head); ***/
s.ins_h = ((s.ins_h = MIN_MATCH) {
/*** INSERT_STRING(s, s.strstart, hash_head); ***/
s.ins_h = ((s.ins_h 4096/*TOO_FAR*/))) {
/* If prev_match is also MIN_MATCH, match_start is garbage
* but we will ignore the current match anyway.
*/
s.match_length = MIN_MATCH - 1;
}
}
/* If there was a match at the previous step and the current
* match is not better, output the previous match:
*/
if (s.prev_length >= MIN_MATCH && s.match_length window[s->strstart-1]));
/*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]);
if (bflush) {
/*** FLUSH_BLOCK_ONLY(s, 0) ***/
flush_block_only(s, false);
/***/
}
s.strstart++;
s.lookahead--;
if (s.strm.avail_out === 0) {
return BS_NEED_MORE;
}
} else {
/* There is no previous match to compare with, wait for
* the next step to decide.
*/
s.match_available = 1;
s.strstart++;
s.lookahead--;
}
}
//Assert (flush != Z_NO_FLUSH, "no flush?");
if (s.match_available) {
//Tracevv((stderr,"%c", s->window[s->strstart-1]));
/*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]);
s.match_available = 0;
}
s.insert = s.strstart = MIN_MATCH && s.strstart > 0) {
scan = s.strstart - 1;
prev = _win[scan];
if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) {
strend = s.strstart + MAX_MATCH;
do {
/*jshint noempty:false*/
} while (prev === _win[++scan] && prev === _win[++scan] &&
prev === _win[++scan] && prev === _win[++scan] &&
prev === _win[++scan] && prev === _win[++scan] &&
prev === _win[++scan] && prev === _win[++scan] &&
scan s.lookahead) {
s.match_length = s.lookahead;
}
}
//Assert(scan window+(uInt)(s->window_size-1), "wild scan");
}
/* Emit match if have run of MIN_MATCH or longer, else emit literal */
if (s.match_length >= MIN_MATCH) {
//check_match(s, s.strstart, s.strstart - 1, s.match_length);
/*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/
bflush = trees._tr_tally(s, 1, s.match_length - MIN_MATCH);
s.lookahead -= s.match_length;
s.strstart += s.match_length;
s.match_length = 0;
} else {
/* No match, output a literal byte */
//Tracevv((stderr,"%c", s->window[s->strstart]));
/*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
bflush = trees._tr_tally(s, 0, s.window[s.strstart]);
s.lookahead--;
s.strstart++;
}
if (bflush) {
/*** FLUSH_BLOCK(s, 0); ***/
flush_block_only(s, false);
if (s.strm.avail_out === 0) {
return BS_NEED_MORE;
}
/***/
}
}
s.insert = 0;
if (flush === Z_FINISH) {
/*** FLUSH_BLOCK(s, 1); ***/
flush_block_only(s, true);
if (s.strm.avail_out === 0) {
return BS_FINISH_STARTED;
}
/***/
return BS_FINISH_DONE;
}
if (s.last_lit) {
/*** FLUSH_BLOCK(s, 0); ***/
flush_block_only(s, false);
if (s.strm.avail_out === 0) {
return BS_NEED_MORE;
}
/***/
}
return BS_BLOCK_DONE;
}
/* ===========================================================================
* For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table.
* (It will be regenerated if this run of deflate switches away from Huffman.)
*/
function deflate_huff(s, flush) {
var bflush; /* set if current block must be flushed */
for (;;) {
/* Make sure that we have a literal to write. */
if (s.lookahead === 0) {
fill_window(s);
if (s.lookahead === 0) {
if (flush === Z_NO_FLUSH) {
return BS_NEED_MORE;
}
break; /* flush the current block */
}
}
/* Output a literal byte */
s.match_length = 0;
//Tracevv((stderr,"%c", s->window[s->strstart]));
/*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
bflush = trees._tr_tally(s, 0, s.window[s.strstart]);
s.lookahead--;
s.strstart++;
if (bflush) {
/*** FLUSH_BLOCK(s, 0); ***/
flush_block_only(s, false);
if (s.strm.avail_out === 0) {
return BS_NEED_MORE;
}
/***/
}
}
s.insert = 0;
if (flush === Z_FINISH) {
/*** FLUSH_BLOCK(s, 1); ***/
flush_block_only(s, true);
if (s.strm.avail_out === 0) {
return BS_FINISH_STARTED;
}
/***/
return BS_FINISH_DONE;
}
if (s.last_lit) {
/*** FLUSH_BLOCK(s, 0); ***/
flush_block_only(s, false);
if (s.strm.avail_out === 0) {
return BS_NEED_MORE;
}
/***/
}
return BS_BLOCK_DONE;
}
/* Values for max_lazy_match, good_match and max_chain_length, depending on
* the desired pack level (0..9). The values given below have been tuned to
* exclude worst case performance for pathological files. Better values may be
* found for specific files.
*/
function Config(good_length, max_lazy, nice_length, max_chain, func) {
this.good_length = good_length;
this.max_lazy = max_lazy;
this.nice_length = nice_length;
this.max_chain = max_chain;
this.func = func;
}
var configuration_table;
configuration_table = [
/* good lazy nice chain */
new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */
new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */
new Config(4, 5, 16, 8, deflate_fast), /* 2 */
new Config(4, 6, 32, 32, deflate_fast), /* 3 */
new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */
new Config(8, 16, 32, 32, deflate_slow), /* 5 */
new Config(8, 16, 128, 128, deflate_slow), /* 6 */
new Config(8, 32, 128, 256, deflate_slow), /* 7 */
new Config(32, 128, 258, 1024, deflate_slow), /* 8 */
new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */
];
/* ===========================================================================
* Initialize the "longest match" routines for a new zlib stream
*/
function lm_init(s) {
s.window_size = 2 * s.w_size;
/*** CLEAR_HASH(s); ***/
zero(s.head); // Fill with NIL (= 0);
/* Set the default configuration parameters:
*/
s.max_lazy_match = configuration_table[s.level].max_lazy;
s.good_match = configuration_table[s.level].good_length;
s.nice_match = configuration_table[s.level].nice_length;
s.max_chain_length = configuration_table[s.level].max_chain;
s.strstart = 0;
s.block_start = 0;
s.lookahead = 0;
s.insert = 0;
s.match_length = s.prev_length = MIN_MATCH - 1;
s.match_available = 0;
s.ins_h = 0;
}
function DeflateState() {
this.strm = null; /* pointer back to this zlib stream */
this.status = 0; /* as the name implies */
this.pending_buf = null; /* output still pending */
this.pending_buf_size = 0; /* size of pending_buf */
this.pending_out = 0; /* next pending byte to output to the stream */
this.pending = 0; /* nb of bytes in the pending buffer */
this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */
this.gzhead = null; /* gzip header information to write */
this.gzindex = 0; /* where in extra, name, or comment */
this.method = Z_DEFLATED; /* can only be DEFLATED */
this.last_flush = -1; /* value of flush param for previous deflate call */
this.w_size = 0; /* LZ77 window size (32K by default) */
this.w_bits = 0; /* log2(w_size) (8..16) */
this.w_mask = 0; /* w_size - 1 */
this.window = null;
/* Sliding window. Input bytes are read into the second half of the window,
* and move to the first half later to keep a dictionary of at least wSize
* bytes. With this organization, matches are limited to a distance of
* wSize-MAX_MATCH bytes, but this ensures that IO is always
* performed with a length multiple of the block size.
*/
this.window_size = 0;
/* Actual size of window: 2*wSize, except when the user input buffer
* is directly used as sliding window.
*/
this.prev = null;
/* Link to older string with same hash index. To limit the size of this
* array to 64K, this link is maintained only for the last 32K strings.
* An index in this array is thus a window index modulo 32K.
*/
this.head = null; /* Heads of the hash chains or NIL. */
this.ins_h = 0; /* hash index of string to be inserted */
this.hash_size = 0; /* number of elements in hash table */
this.hash_bits = 0; /* log2(hash_size) */
this.hash_mask = 0; /* hash_size-1 */
this.hash_shift = 0;
/* Number of bits by which ins_h must be shifted at each input
* step. It must be such that after MIN_MATCH steps, the oldest
* byte no longer takes part in the hash key, that is:
* hash_shift * MIN_MATCH >= hash_bits
*/
this.block_start = 0;
/* Window position at the beginning of the current output block. Gets
* negative when the window is moved backwards.
*/
this.match_length = 0; /* length of best match */
this.prev_match = 0; /* previous match */
this.match_available = 0; /* set if previous match exists */
this.strstart = 0; /* start of string to insert */
this.match_start = 0; /* start of matching string */
this.lookahead = 0; /* number of valid bytes ahead in window */
this.prev_length = 0;
/* Length of the best match at previous step. Matches not greater than this
* are discarded. This is used in the lazy match evaluation.
*/
this.max_chain_length = 0;
/* To speed up deflation, hash chains are never searched beyond this
* length. A higher limit improves compression ratio but degrades the
* speed.
*/
this.max_lazy_match = 0;
/* Attempt to find a better match only when the current match is strictly
* smaller than this value. This mechanism is used only for compression
* levels >= 4.
*/
// That's alias to max_lazy_match, don't use directly
//this.max_insert_length = 0;
/* Insert new strings in the hash table only if the match length is not
* greater than this length. This saves time but degrades compression.
* max_insert_length is used only for compression levels 15) {
wrap = 2; /* write gzip wrapper instead */
windowBits -= 16;
}
if (memLevel MAX_MEM_LEVEL || method !== Z_DEFLATED ||
windowBits 15 || level 9 ||
strategy Z_FIXED) {
return err(strm, Z_STREAM_ERROR);
}
if (windowBits === 8) {
windowBits = 9;
}
/* until 256-byte window bug fixed */
var s = new DeflateState();
strm.state = s;
s.strm = strm;
s.wrap = wrap;
s.gzhead = null;
s.w_bits = windowBits;
s.w_size = 1 window yet */
s.lit_bufsize = 1 lit_bufsize, sizeof(ush)+2);
//s->pending_buf = (uchf *) overlay;
s.pending_buf = new utils.Buf8(s.pending_buf_size);
// It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`)
//s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
s.d_buf = 1 * s.lit_bufsize;
//s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
s.l_buf = (1 + 2) * s.lit_bufsize;
s.level = level;
s.strategy = strategy;
s.method = method;
return deflateReset(strm);
}
function deflateInit(strm, level) {
return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
}
function deflate(strm, flush) {
var old_flush, s;
var beg, val; // for gzip header write only
if (!strm || !strm.state ||
flush > Z_BLOCK || flush gzhead == Z_NULL
put_byte(s, 0);
put_byte(s, 0);
put_byte(s, 0);
put_byte(s, 0);
put_byte(s, 0);
put_byte(s, s.level === 9 ? 2 :
(s.strategy >= Z_HUFFMAN_ONLY || s.level > 8) & 0xff);
put_byte(s, (s.gzhead.time >> 16) & 0xff);
put_byte(s, (s.gzhead.time >> 24) & 0xff);
put_byte(s, s.level === 9 ? 2 :
(s.strategy >= Z_HUFFMAN_ONLY || s.level > 8) & 0xff);
}
if (s.gzhead.hcrc) {
strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0);
}
s.gzindex = 0;
s.status = EXTRA_STATE;
}
}
else // DEFLATE header
{
var header = (Z_DEFLATED + ((s.w_bits - 8) = Z_HUFFMAN_ONLY || s.level >> 16);
putShortMSB(s, strm.adler & 0xffff);
}
strm.adler = 1; // adler32(0L, Z_NULL, 0);
}
}
//#ifdef GZIP
if (s.status === EXTRA_STATE) {
if (s.gzhead.extra/* != Z_NULL*/) {
beg = s.pending; /* start of bytes to update crc */
while (s.gzindex beg) {
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
}
flush_pending(strm);
beg = s.pending;
if (s.pending === s.pending_buf_size) {
break;
}
}
put_byte(s, s.gzhead.extra[s.gzindex] & 0xff);
s.gzindex++;
}
if (s.gzhead.hcrc && s.pending > beg) {
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
}
if (s.gzindex === s.gzhead.extra.length) {
s.gzindex = 0;
s.status = NAME_STATE;
}
}
else {
s.status = NAME_STATE;
}
}
if (s.status === NAME_STATE) {
if (s.gzhead.name/* != Z_NULL*/) {
beg = s.pending; /* start of bytes to update crc */
//int val;
do {
if (s.pending === s.pending_buf_size) {
if (s.gzhead.hcrc && s.pending > beg) {
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
}
flush_pending(strm);
beg = s.pending;
if (s.pending === s.pending_buf_size) {
val = 1;
break;
}
}
// JS specific: little magic to add zero terminator to end of string
if (s.gzindex beg) {
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
}
if (val === 0) {
s.gzindex = 0;
s.status = COMMENT_STATE;
}
}
else {
s.status = COMMENT_STATE;
}
}
if (s.status === COMMENT_STATE) {
if (s.gzhead.comment/* != Z_NULL*/) {
beg = s.pending; /* start of bytes to update crc */
//int val;
do {
if (s.pending === s.pending_buf_size) {
if (s.gzhead.hcrc && s.pending > beg) {
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
}
flush_pending(strm);
beg = s.pending;
if (s.pending === s.pending_buf_size) {
val = 1;
break;
}
}
// JS specific: little magic to add zero terminator to end of string
if (s.gzindex beg) {
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
}
if (val === 0) {
s.status = HCRC_STATE;
}
}
else {
s.status = HCRC_STATE;
}
}
if (s.status === HCRC_STATE) {
if (s.gzhead.hcrc) {
if (s.pending + 2 > s.pending_buf_size) {
flush_pending(strm);
}
if (s.pending + 2 > 8) & 0xff);
strm.adler = 0; //crc32(0L, Z_NULL, 0);
s.status = BUSY_STATE;
}
}
else {
s.status = BUSY_STATE;
}
}
//#endif
/* Flush as much pending output as possible */
if (s.pending !== 0) {
flush_pending(strm);
if (strm.avail_out === 0) {
/* Since avail_out is 0, deflate will be called again with
* more output space, but possibly with both pending and
* avail_in equal to zero. There won't be anything to do,
* but this is not an error situation so make sure we
* return OK instead of BUF_ERROR at next call of deflate:
*/
s.last_flush = -1;
return Z_OK;
}
/* Make sure there is something to do and avoid duplicate consecutive
* flushes. For repeated and useless calls with Z_FINISH, we keep
* returning Z_STREAM_END instead of Z_BUF_ERROR.
*/
} else if (strm.avail_in === 0 && rank(flush) avail_out > 0, "bug2");
//if (strm.avail_out > 8) & 0xff);
put_byte(s, (strm.adler >> 16) & 0xff);
put_byte(s, (strm.adler >> 24) & 0xff);
put_byte(s, strm.total_in & 0xff);
put_byte(s, (strm.total_in >> 8) & 0xff);
put_byte(s, (strm.total_in >> 16) & 0xff);
put_byte(s, (strm.total_in >> 24) & 0xff);
}
else
{
putShortMSB(s, strm.adler >>> 16);
putShortMSB(s, strm.adler & 0xffff);
}
flush_pending(strm);
/* If avail_out is zero, the application will call deflate again
* to flush the rest.
*/
if (s.wrap > 0) { s.wrap = -s.wrap; }
/* write the trailer only once! */
return s.pending !== 0 ? Z_OK : Z_STREAM_END;
}
function deflateEnd(strm) {
var status;
if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) {
return Z_STREAM_ERROR;
}
status = strm.state.status;
if (status !== INIT_STATE &&
status !== EXTRA_STATE &&
status !== NAME_STATE &&
status !== COMMENT_STATE &&
status !== HCRC_STATE &&
status !== BUSY_STATE &&
status !== FINISH_STATE
) {
return err(strm, Z_STREAM_ERROR);
}
strm.state = null;
return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK;
}
/* =========================================================================
* Initializes the compression dictionary from the given byte
* sequence without producing any compressed output.
*/
function deflateSetDictionary(strm, dictionary) {
var dictLength = dictionary.length;
var s;
var str, n;
var wrap;
var avail;
var next;
var input;
var tmpDict;
if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) {
return Z_STREAM_ERROR;
}
s = strm.state;
wrap = s.wrap;
if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) {
return Z_STREAM_ERROR;
}
/* when using zlib wrappers, compute Adler-32 for provided dictionary */
if (wrap === 1) {
/* adler32(strm->adler, dictionary, dictLength); */
strm.adler = adler32(strm.adler, dictionary, dictLength, 0);
}
s.wrap = 0; /* avoid computing Adler-32 in read_buf */
/* if dictionary would fill window, just replace the history */
if (dictLength >= s.w_size) {
if (wrap === 0) { /* already empty otherwise */
/*** CLEAR_HASH(s); ***/
zero(s.head); // Fill with NIL (= 0);
s.strstart = 0;
s.block_start = 0;
s.insert = 0;
}
/* use the tail */
// dictionary = dictionary.slice(dictLength - s.w_size);
tmpDict = new utils.Buf8(s.w_size);
utils.arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0);
dictionary = tmpDict;
dictLength = s.w_size;
}
/* insert dictionary into window and hash */
avail = strm.avail_in;
next = strm.next_in;
input = strm.input;
strm.avail_in = dictLength;
strm.next_in = 0;
strm.input = dictionary;
fill_window(s);
while (s.lookahead >= MIN_MATCH) {
str = s.strstart;
n = s.lookahead - (MIN_MATCH - 1);
do {
/* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */
s.ins_h = ((s.ins_h = 6
strm.avail_out >= 258
start >= strm.avail_out
state.bits = 6, then there is enough input to avoid
checking for available input while decoding.
- The maximum bytes that a single length/distance pair can output is 258
bytes, which is the maximum length that can be coded. inflate_fast()
requires strm.avail_out >= 258 for each loop to avoid checking for
output space.
*/
module.exports = function inflate_fast(strm, start) {
var state;
var _in; /* local strm.input */
var last; /* have enough input while in >> 24/*here.bits*/;
hold >>>= op;
bits -= op;
op = (here >>> 16) & 0xff/*here.op*/;
if (op === 0) { /* literal */
//Tracevv((stderr, here.val >= 0x20 && here.val >>= op;
bits -= op;
}
//Tracevv((stderr, "inflate: length %u\n", len));
if (bits >> 24/*here.bits*/;
hold >>>= op;
bits -= op;
op = (here >>> 16) & 0xff/*here.op*/;
if (op & 16) { /* distance base */
dist = here & 0xffff/*here.val*/;
op &= 15; /* number of extra bits */
if (bits dmax) {
strm.msg = 'invalid distance too far back';
state.mode = BAD;
break top;
}
//#endif
hold >>>= op;
bits -= op;
//Tracevv((stderr, "inflate: distance %u\n", dist));
op = _out - beg; /* max distance in output */
if (dist > op) { /* see if copy from window */
op = dist - op; /* distance back in window */
if (op > whave) {
if (state.sane) {
strm.msg = 'invalid distance too far back';
state.mode = BAD;
break top;
}
// (!) This block is disabled in zlib defailts,
// don't enable it for binary compatibility
//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
// if (len whave);
// if (op === 0) {
// from = _out - dist;
// do {
// output[_out++] = output[from++];
// } while (--len);
// continue top;
// }
//#endif
}
from = 0; // window index
from_source = s_window;
if (wnext === 0) { /* very common case */
from += wsize - op;
if (op 2) {
output[_out++] = from_source[from++];
output[_out++] = from_source[from++];
output[_out++] = from_source[from++];
len -= 3;
}
if (len) {
output[_out++] = from_source[from++];
if (len > 1) {
output[_out++] = from_source[from++];
}
}
}
else {
from = _out - dist; /* copy direct from output */
do { /* minimum length is three */
output[_out++] = output[from++];
output[_out++] = output[from++];
output[_out++] = output[from++];
len -= 3;
} while (len > 2);
if (len) {
output[_out++] = output[from++];
if (len > 1) {
output[_out++] = output[from++];
}
}
}
}
else if ((op & 64) === 0) { /* 2nd level distance code */
here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 > 3;
_in -= len;
bits -= len >> 24) & 0xff) +
((q >>> 8) & 0xff00) +
((q & 0xff00) > 4) + 1;
if (windowBits 15)) {
return Z_STREAM_ERROR;
}
if (state.window !== null && state.wbits !== windowBits) {
state.window = null;
}
/* update state and reset the rest of it */
state.wrap = wrap;
state.wbits = windowBits;
return inflateReset(strm);
}
function inflateInit2(strm, windowBits) {
var ret;
var state;
if (!strm) { return Z_STREAM_ERROR; }
//strm.msg = Z_NULL; /* in case we return an error */
state = new InflateState();
//if (state === Z_NULL) return Z_MEM_ERROR;
//Tracev((stderr, "inflate: allocated\n"));
strm.state = state;
state.window = null/*Z_NULL*/;
ret = inflateReset2(strm, windowBits);
if (ret !== Z_OK) {
strm.state = null/*Z_NULL*/;
}
return ret;
}
function inflateInit(strm) {
return inflateInit2(strm, DEF_WBITS);
}
/*
Return state with length and distance decoding tables and index sizes set to
fixed code decoding. Normally this returns fixed tables from inffixed.h.
If BUILDFIXED is defined, then instead this routine builds the tables the
first time it's called, and returns those tables the first time and
thereafter. This reduces the size of the code by about 2K bytes, in
exchange for a little execution time. However, BUILDFIXED should not be
used for threaded applications, since the rewriting of the tables and virgin
may not be thread-safe.
*/
var virgin = true;
var lenfix, distfix; // We have no pointers in JS, so keep tables separate
function fixedtables(state) {
/* build fixed huffman tables if first call (may not be thread safe) */
if (virgin) {
var sym;
lenfix = new utils.Buf32(512);
distfix = new utils.Buf32(32);
/* literal/length table */
sym = 0;
while (sym wsize or less output bytes into the circular window */
if (copy >= state.wsize) {
utils.arraySet(state.window, src, end - state.wsize, state.wsize, 0);
state.wnext = 0;
state.whave = state.wsize;
}
else {
dist = state.wsize - state.wnext;
if (dist > copy) {
dist = copy;
}
//zmemcpy(state->window + state->wnext, end - copy, dist);
utils.arraySet(state.window, src, end - copy, dist, state.wnext);
copy -= dist;
if (copy) {
//zmemcpy(state->window, end - copy, copy);
utils.arraySet(state.window, src, end - copy, copy, 0);
state.wnext = copy;
state.whave = state.wsize;
}
else {
state.wnext += dist;
if (state.wnext === state.wsize) { state.wnext = 0; }
if (state.whave >> 8) & 0xff;
state.check = crc32(state.check, hbuf, 2, 0);
//===//
//=== INITBITS();
hold = 0;
bits = 0;
//===//
state.mode = FLAGS;
break;
}
state.flags = 0; /* expect zlib header */
if (state.head) {
state.head.done = false;
}
if (!(state.wrap & 1) || /* check if zlib header allowed */
(((hold & 0xff)/*BITS(8)*/ > 8)) % 31) {
strm.msg = 'incorrect header check';
state.mode = BAD;
break;
}
if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) {
strm.msg = 'unknown compression method';
state.mode = BAD;
break;
}
//--- DROPBITS(4) ---//
hold >>>= 4;
bits -= 4;
//---//
len = (hold & 0x0f)/*BITS(4)*/ + 8;
if (state.wbits === 0) {
state.wbits = len;
}
else if (len > state.wbits) {
strm.msg = 'invalid window size';
state.mode = BAD;
break;
}
state.dmax = 1 > 8) & 1);
}
if (state.flags & 0x0200) {
//=== CRC2(state.check, hold);
hbuf[0] = hold & 0xff;
hbuf[1] = (hold >>> 8) & 0xff;
state.check = crc32(state.check, hbuf, 2, 0);
//===//
}
//=== INITBITS();
hold = 0;
bits = 0;
//===//
state.mode = TIME;
/* falls through */
case TIME:
//=== NEEDBITS(32); */
while (bits >> 8) & 0xff;
hbuf[2] = (hold >>> 16) & 0xff;
hbuf[3] = (hold >>> 24) & 0xff;
state.check = crc32(state.check, hbuf, 4, 0);
//===
}
//=== INITBITS();
hold = 0;
bits = 0;
//===//
state.mode = OS;
/* falls through */
case OS:
//=== NEEDBITS(16); */
while (bits > 8);
}
if (state.flags & 0x0200) {
//=== CRC2(state.check, hold);
hbuf[0] = hold & 0xff;
hbuf[1] = (hold >>> 8) & 0xff;
state.check = crc32(state.check, hbuf, 2, 0);
//===//
}
//=== INITBITS();
hold = 0;
bits = 0;
//===//
state.mode = EXLEN;
/* falls through */
case EXLEN:
if (state.flags & 0x0400) {
//=== NEEDBITS(16); */
while (bits >> 8) & 0xff;
state.check = crc32(state.check, hbuf, 2, 0);
//===//
}
//=== INITBITS();
hold = 0;
bits = 0;
//===//
}
else if (state.head) {
state.head.extra = null/*Z_NULL*/;
}
state.mode = EXTRA;
/* falls through */
case EXTRA:
if (state.flags & 0x0400) {
copy = state.length;
if (copy > have) { copy = have; }
if (copy) {
if (state.head) {
len = state.head.extra_len - state.length;
if (!state.head.extra) {
// Use untyped array for more conveniend processing later
state.head.extra = new Array(state.head.extra_len);
}
utils.arraySet(
state.head.extra,
input,
next,
// extra field is limited to 65536 bytes
// - no need for additional size check
copy,
/*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/
len
);
//zmemcpy(state.head.extra + len, next,
// len + copy > state.head.extra_max ?
// state.head.extra_max - len : copy);
}
if (state.flags & 0x0200) {
state.check = crc32(state.check, input, copy, next);
}
have -= copy;
next += copy;
state.length -= copy;
}
if (state.length) { break inf_leave; }
}
state.length = 0;
state.mode = NAME;
/* falls through */
case NAME:
if (state.flags & 0x0800) {
if (have === 0) { break inf_leave; }
copy = 0;
do {
// TODO: 2 or 1 bytes?
len = input[next + copy++];
/* use constant limit because in js we should not preallocate memory */
if (state.head && len &&
(state.length > 9) & 1);
state.head.done = true;
}
strm.adler = state.check = 0;
state.mode = TYPE;
break;
case DICTID:
//=== NEEDBITS(32); */
while (bits >>= bits & 7;
bits -= bits & 7;
//---//
state.mode = CHECK;
break;
}
//=== NEEDBITS(3); */
while (bits >>= 1;
bits -= 1;
//---//
switch ((hold & 0x03)/*BITS(2)*/) {
case 0: /* stored block */
//Tracev((stderr, "inflate: stored block%s\n",
// state.last ? " (last)" : ""));
state.mode = STORED;
break;
case 1: /* fixed block */
fixedtables(state);
//Tracev((stderr, "inflate: fixed codes block%s\n",
// state.last ? " (last)" : ""));
state.mode = LEN_; /* decode codes */
if (flush === Z_TREES) {
//--- DROPBITS(2) ---//
hold >>>= 2;
bits -= 2;
//---//
break inf_leave;
}
break;
case 2: /* dynamic block */
//Tracev((stderr, "inflate: dynamic codes block%s\n",
// state.last ? " (last)" : ""));
state.mode = TABLE;
break;
case 3:
strm.msg = 'invalid block type';
state.mode = BAD;
}
//--- DROPBITS(2) ---//
hold >>>= 2;
bits -= 2;
//---//
break;
case STORED:
//--- BYTEBITS() ---// /* go to byte boundary */
hold >>>= bits & 7;
bits -= bits & 7;
//---//
//=== NEEDBITS(32); */
while (bits >> 16) ^ 0xffff)) {
strm.msg = 'invalid stored block lengths';
state.mode = BAD;
break;
}
state.length = hold & 0xffff;
//Tracev((stderr, "inflate: stored length %u\n",
// state.length));
//=== INITBITS();
hold = 0;
bits = 0;
//===//
state.mode = COPY_;
if (flush === Z_TREES) { break inf_leave; }
/* falls through */
case COPY_:
state.mode = COPY;
/* falls through */
case COPY:
copy = state.length;
if (copy) {
if (copy > have) { copy = have; }
if (copy > left) { copy = left; }
if (copy === 0) { break inf_leave; }
//--- zmemcpy(put, next, copy); ---
utils.arraySet(output, input, next, copy, put);
//---//
have -= copy;
next += copy;
left -= copy;
put += copy;
state.length -= copy;
break;
}
//Tracev((stderr, "inflate: stored end\n"));
state.mode = TYPE;
break;
case TABLE:
//=== NEEDBITS(14); */
while (bits >>= 5;
bits -= 5;
//---//
state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1;
//--- DROPBITS(5) ---//
hold >>>= 5;
bits -= 5;
//---//
state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4;
//--- DROPBITS(4) ---//
hold >>>= 4;
bits -= 4;
//---//
//#ifndef PKZIP_BUG_WORKAROUND
if (state.nlen > 286 || state.ndist > 30) {
strm.msg = 'too many length or distance symbols';
state.mode = BAD;
break;
}
//#endif
//Tracev((stderr, "inflate: table sizes ok\n"));
state.have = 0;
state.mode = LENLENS;
/* falls through */
case LENLENS:
while (state.have >>= 3;
bits -= 3;
//---//
}
while (state.have >> 24;
here_op = (here >>> 16) & 0xff;
here_val = here & 0xffff;
if ((here_bits) >>= here_bits;
bits -= here_bits;
//---//
state.lens[state.have++] = here_val;
}
else {
if (here_val === 16) {
//=== NEEDBITS(here.bits + 2);
n = here_bits + 2;
while (bits >>= here_bits;
bits -= here_bits;
//---//
if (state.have === 0) {
strm.msg = 'invalid bit length repeat';
state.mode = BAD;
break;
}
len = state.lens[state.have - 1];
copy = 3 + (hold & 0x03);//BITS(2);
//--- DROPBITS(2) ---//
hold >>>= 2;
bits -= 2;
//---//
}
else if (here_val === 17) {
//=== NEEDBITS(here.bits + 3);
n = here_bits + 3;
while (bits >>= here_bits;
bits -= here_bits;
//---//
len = 0;
copy = 3 + (hold & 0x07);//BITS(3);
//--- DROPBITS(3) ---//
hold >>>= 3;
bits -= 3;
//---//
}
else {
//=== NEEDBITS(here.bits + 7);
n = here_bits + 7;
while (bits >>= here_bits;
bits -= here_bits;
//---//
len = 0;
copy = 11 + (hold & 0x7f);//BITS(7);
//--- DROPBITS(7) ---//
hold >>>= 7;
bits -= 7;
//---//
}
if (state.have + copy > state.nlen + state.ndist) {
strm.msg = 'invalid bit length repeat';
state.mode = BAD;
break;
}
while (copy--) {
state.lens[state.have++] = len;
}
}
}
/* handle error breaks in while */
if (state.mode === BAD) { break; }
/* check for end-of-block code (better have one) */
if (state.lens[256] === 0) {
strm.msg = 'invalid code -- missing end-of-block';
state.mode = BAD;
break;
}
/* build code tables -- note: do not change the lenbits or distbits
values here (9 and 6) without reading the comments in inftrees.h
concerning the ENOUGH constants, which depend on those values */
state.lenbits = 9;
opts = { bits: state.lenbits };
ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts);
// We have separate tables & no pointers. 2 commented lines below not needed.
// state.next_index = opts.table_index;
state.lenbits = opts.bits;
// state.lencode = state.next;
if (ret) {
strm.msg = 'invalid literal/lengths set';
state.mode = BAD;
break;
}
state.distbits = 6;
//state.distcode.copy(state.codes);
// Switch to use dynamic table
state.distcode = state.distdyn;
opts = { bits: state.distbits };
ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts);
// We have separate tables & no pointers. 2 commented lines below not needed.
// state.next_index = opts.table_index;
state.distbits = opts.bits;
// state.distcode = state.next;
if (ret) {
strm.msg = 'invalid distances set';
state.mode = BAD;
break;
}
//Tracev((stderr, 'inflate: codes ok\n'));
state.mode = LEN_;
if (flush === Z_TREES) { break inf_leave; }
/* falls through */
case LEN_:
state.mode = LEN;
/* falls through */
case LEN:
if (have >= 6 && left >= 258) {
//--- RESTORE() ---
strm.next_out = put;
strm.avail_out = left;
strm.next_in = next;
strm.avail_in = have;
state.hold = hold;
state.bits = bits;
//---
inflate_fast(strm, _out);
//--- LOAD() ---
put = strm.next_out;
output = strm.output;
left = strm.avail_out;
next = strm.next_in;
input = strm.input;
have = strm.avail_in;
hold = state.hold;
bits = state.bits;
//---
if (state.mode === TYPE) {
state.back = -1;
}
break;
}
state.back = 0;
for (;;) {
here = state.lencode[hold & ((1 >> 24;
here_op = (here >>> 16) & 0xff;
here_val = here & 0xffff;
if (here_bits > last_bits)];
here_bits = here >>> 24;
here_op = (here >>> 16) & 0xff;
here_val = here & 0xffff;
if ((last_bits + here_bits) >>= last_bits;
bits -= last_bits;
//---//
state.back += last_bits;
}
//--- DROPBITS(here.bits) ---//
hold >>>= here_bits;
bits -= here_bits;
//---//
state.back += here_bits;
state.length = here_val;
if (here_op === 0) {
//Tracevv((stderr, here.val >= 0x20 && here.val >>= state.extra;
bits -= state.extra;
//---//
state.back += state.extra;
}
//Tracevv((stderr, "inflate: length %u\n", state.length));
state.was = state.length;
state.mode = DIST;
/* falls through */
case DIST:
for (;;) {
here = state.distcode[hold & ((1 >> 24;
here_op = (here >>> 16) & 0xff;
here_val = here & 0xffff;
if ((here_bits) > last_bits)];
here_bits = here >>> 24;
here_op = (here >>> 16) & 0xff;
here_val = here & 0xffff;
if ((last_bits + here_bits) >>= last_bits;
bits -= last_bits;
//---//
state.back += last_bits;
}
//--- DROPBITS(here.bits) ---//
hold >>>= here_bits;
bits -= here_bits;
//---//
state.back += here_bits;
if (here_op & 64) {
strm.msg = 'invalid distance code';
state.mode = BAD;
break;
}
state.offset = here_val;
state.extra = (here_op) & 15;
state.mode = DISTEXT;
/* falls through */
case DISTEXT:
if (state.extra) {
//=== NEEDBITS(state.extra);
n = state.extra;
while (bits >>= state.extra;
bits -= state.extra;
//---//
state.back += state.extra;
}
//#ifdef INFLATE_STRICT
if (state.offset > state.dmax) {
strm.msg = 'invalid distance too far back';
state.mode = BAD;
break;
}
//#endif
//Tracevv((stderr, "inflate: distance %u\n", state.offset));
state.mode = MATCH;
/* falls through */
case MATCH:
if (left === 0) { break inf_leave; }
copy = _out - left;
if (state.offset > copy) { /* copy from window */
copy = state.offset - copy;
if (copy > state.whave) {
if (state.sane) {
strm.msg = 'invalid distance too far back';
state.mode = BAD;
break;
}
// (!) This block is disabled in zlib defailts,
// don't enable it for binary compatibility
//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
// Trace((stderr, "inflate.c too far\n"));
// copy -= state.whave;
// if (copy > state.length) { copy = state.length; }
// if (copy > left) { copy = left; }
// left -= copy;
// state.length -= copy;
// do {
// output[put++] = 0;
// } while (--copy);
// if (state.length === 0) { state.mode = LEN; }
// break;
//#endif
}
if (copy > state.wnext) {
copy -= state.wnext;
from = state.wsize - copy;
}
else {
from = state.wnext - copy;
}
if (copy > state.length) { copy = state.length; }
from_source = state.window;
}
else { /* copy from output */
from_source = output;
from = put - state.offset;
copy = state.length;
}
if (copy > left) { copy = left; }
left -= copy;
state.length -= copy;
do {
output[put++] = from_source[from++];
} while (--copy);
if (state.length === 0) { state.mode = LEN; }
break;
case LIT:
if (left === 0) { break inf_leave; }
output[put++] = state.length;
left--;
state.mode = LEN;
break;
case CHECK:
if (state.wrap) {
//=== NEEDBITS(32);
while (bits zfree == (free_func)0*/) {
return Z_STREAM_ERROR;
}
var state = strm.state;
if (state.window) {
state.window = null;
}
strm.state = null;
return Z_OK;
}
function inflateGetHeader(strm, head) {
var state;
/* check state */
if (!strm || !strm.state) { return Z_STREAM_ERROR; }
state = strm.state;
if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; }
/* save header structure */
state.head = head;
head.done = false;
return Z_OK;
}
function inflateSetDictionary(strm, dictionary) {
var dictLength = dictionary.length;
var state;
var dictid;
var ret;
/* check state */
if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; }
state = strm.state;
if (state.wrap !== 0 && state.mode !== DICT) {
return Z_STREAM_ERROR;
}
/* check for correct dictionary identifier */
if (state.mode === DICT) {
dictid = 1; /* adler32(0, null, 0)*/
/* dictid = adler32(dictid, dictionary, dictLength); */
dictid = adler32(dictid, dictionary, dictLength, 0);
if (dictid !== state.check) {
return Z_DATA_ERROR;
}
}
/* copy dictionary to window using updatewindow(), which will amend the
existing dictionary if appropriate */
ret = updatewindow(strm, dictionary, dictLength, dictLength);
if (ret) {
state.mode = MEM;
return Z_MEM_ERROR;
}
state.havedict = 1;
// Tracev((stderr, "inflate: dictionary set\n"));
return Z_OK;
}
exports.inflateReset = inflateReset;
exports.inflateReset2 = inflateReset2;
exports.inflateResetKeep = inflateResetKeep;
exports.inflateInit = inflateInit;
exports.inflateInit2 = inflateInit2;
exports.inflate = inflate;
exports.inflateEnd = inflateEnd;
exports.inflateGetHeader = inflateGetHeader;
exports.inflateSetDictionary = inflateSetDictionary;
exports.inflateInfo = 'pako inflate (from Nodeca project)';
/* Not implemented
exports.inflateCopy = inflateCopy;
exports.inflateGetDictionary = inflateGetDictionary;
exports.inflateMark = inflateMark;
exports.inflatePrime = inflatePrime;
exports.inflateSync = inflateSync;
exports.inflateSyncPoint = inflateSyncPoint;
exports.inflateUndermine = inflateUndermine;
*/
},{"../utils/common":41,"./adler32":43,"./crc32":45,"./inffast":48,"./inftrees":50}],50:[function(require,module,exports){
'use strict';
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
var utils = require('../utils/common');
var MAXBITS = 15;
var ENOUGH_LENS = 852;
var ENOUGH_DISTS = 592;
//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);
var CODES = 0;
var LENS = 1;
var DISTS = 2;
var lbase = [ /* Length codes 257..285 base */
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
];
var lext = [ /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78
];
var dbase = [ /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577, 0, 0
];
var dext = [ /* Distance codes 0..29 extra */
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
28, 28, 29, 29, 64, 64
];
module.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts)
{
var bits = opts.bits;
//here = opts.here; /* table entry for duplication */
var len = 0; /* a code's length in bits */
var sym = 0; /* index of code symbols */
var min = 0, max = 0; /* minimum and maximum code lengths */
var root = 0; /* number of index bits for root table */
var curr = 0; /* number of index bits for current table */
var drop = 0; /* code bits to drop for sub-table */
var left = 0; /* number of prefix codes available */
var used = 0; /* code entries in table used */
var huff = 0; /* Huffman code */
var incr; /* for incrementing code, index */
var fill; /* index for replicating entries */
var low; /* low bits for current root entry */
var mask; /* mask for low root bits */
var next; /* next available space in table */
var base = null; /* base value table to use */
var base_index = 0;
// var shoextra; /* extra bits table to use */
var end; /* use base and extra for symbol > end */
var count = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */
var offs = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */
var extra = null;
var extra_index = 0;
var here_bits, here_op, here_val;
/*
Process a set of code lengths to create a canonical Huffman code. The
code lengths are lens[0..codes-1]. Each length corresponds to the
symbols 0..codes-1. The Huffman code is generated by first sorting the
symbols by length from short to long, and retaining the symbol order
for codes with equal lengths. Then the code starts with all zero bits
for the first code of the shortest length, and the codes are integer
increments for the same length, and zeros are appended as the length
increases. For the deflate format, these bits are stored backwards
from their more natural integer increment ordering, and so when the
decoding tables are built in the large loop below, the integer codes
are incremented backwards.
This routine assumes, but does not check, that all of the entries in
lens[] are in the range 0..MAXBITS. The caller must assure this.
1..MAXBITS is interpreted as that code length. zero means that that
symbol does not occur in this code.
The codes are sorted by computing a count of codes for each length,
creating from that a table of starting indices for each length in the
sorted table, and then entering the symbols in order in the sorted
table. The sorted table is work[], with that space being provided by
the caller.
The length counts are used for other purposes as well, i.e. finding
the minimum and maximum length codes, determining if there are any
codes at all, checking for a valid set of lengths, and looking ahead
at length counts to determine sub-table sizes when building the
decoding tables.
*/
/* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
for (len = 0; len = 1; max--) {
if (count[max] !== 0) { break; }
}
if (root > max) {
root = max;
}
if (max === 0) { /* no symbols to code at all */
//table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */
//table.bits[opts.table_index] = 1; //here.bits = (var char)1;
//table.val[opts.table_index++] = 0; //here.val = (var short)0;
table[table_index++] = (1 0 && (type === CODES || max !== 1)) {
return -1; /* incomplete set */
}
/* generate offsets into symbol table for each length for sorting */
offs[1] = 0;
for (len = 1; len root */
used = 1 ENOUGH_LENS) ||
(type === DISTS && used > ENOUGH_DISTS)) {
return 1;
}
/* process all codes and make table entries */
for (;;) {
/* create table entry */
here_bits = len - drop;
if (work[sym] end) {
here_op = extra[extra_index + work[sym]];
here_val = base[base_index + work[sym]];
}
else {
here_op = 32 + 64; /* end of block */
here_val = 0;
}
/* replicate for those indices with low len bits equal to huff */
incr = 1 > drop) + fill] = (here_bits >= 1;
}
if (incr !== 0) {
huff &= incr - 1;
huff += incr;
} else {
huff = 0;
}
/* go to next symbol, update count, len */
sym++;
if (--count[len] === 0) {
if (len === max) { break; }
len = lens[lens_index + work[sym]];
}
/* create new sub-table if needed */
if (len > root && (huff & mask) !== low) {
/* if first time, transition to sub-tables */
if (drop === 0) {
drop = root;
}
/* increment past last table */
next += min; /* here min is 1 ENOUGH_LENS) ||
(type === DISTS && used > ENOUGH_DISTS)) {
return 1;
}
/* point entry in root table to sub-table */
low = huff & mask;
/*table.op[low] = curr;
table.bits[low] = root;
table.val[low] = next - opts.table_index;*/
table[low] = (root = 0) { buf[len] = 0; } }
// From zutil.h
var STORED_BLOCK = 0;
var STATIC_TREES = 1;
var DYN_TREES = 2;
/* The three kinds of block type */
var MIN_MATCH = 3;
var MAX_MATCH = 258;
/* The minimum and maximum match lengths */
// From deflate.h
/* ===========================================================================
* Internal compression state.
*/
var LENGTH_CODES = 29;
/* number of length codes, not counting the special END_BLOCK code */
var LITERALS = 256;
/* number of literal bytes 0..255 */
var L_CODES = LITERALS + 1 + LENGTH_CODES;
/* number of Literal or Length codes, including the END_BLOCK code */
var D_CODES = 30;
/* number of distance codes */
var BL_CODES = 19;
/* number of codes used to transfer the bit lengths */
var HEAP_SIZE = 2 * L_CODES + 1;
/* maximum heap size */
var MAX_BITS = 15;
/* All codes must not exceed MAX_BITS bits */
var Buf_size = 16;
/* size of bit buffer in bi_buf */
/* ===========================================================================
* Constants
*/
var MAX_BL_BITS = 7;
/* Bit length codes must not exceed MAX_BL_BITS bits */
var END_BLOCK = 256;
/* end of block literal code */
var REP_3_6 = 16;
/* repeat previous bit length 3-6 times (2 bits of repeat count) */
var REPZ_3_10 = 17;
/* repeat a zero length 3-10 times (3 bits of repeat count) */
var REPZ_11_138 = 18;
/* repeat a zero length 11-138 times (7 bits of repeat count) */
/* eslint-disable comma-spacing,array-bracket-spacing */
var extra_lbits = /* extra bits for each length code */
[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0];
var extra_dbits = /* extra bits for each distance code */
[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13];
var extra_blbits = /* extra bits for each bit length code */
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7];
var bl_order =
[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];
/* eslint-enable comma-spacing,array-bracket-spacing */
/* The lengths of the bit length codes are sent in order of decreasing
* probability, to avoid transmitting the lengths for unused bit length codes.
*/
/* ===========================================================================
* Local data. These are initialized only once.
*/
// We pre-fill arrays with 0 to avoid uninitialized gaps
var DIST_CODE_LEN = 512; /* see definition of array dist_code below */
// !!!! Use flat array insdead of structure, Freq = i*2, Len = i*2+1
var static_ltree = new Array((L_CODES + 2) * 2);
zero(static_ltree);
/* The static literal tree. Since the bit lengths are imposed, there is no
* need for the L_CODES extra codes used during heap construction. However
* The codes 286 and 287 are needed to build a canonical tree (see _tr_init
* below).
*/
var static_dtree = new Array(D_CODES * 2);
zero(static_dtree);
/* The static distance tree. (Actually a trivial tree since all codes use
* 5 bits.)
*/
var _dist_code = new Array(DIST_CODE_LEN);
zero(_dist_code);
/* Distance codes. The first 256 values correspond to the distances
* 3 .. 258, the last 256 values correspond to the top 8 bits of
* the 15 bit distances.
*/
var _length_code = new Array(MAX_MATCH - MIN_MATCH + 1);
zero(_length_code);
/* length code for each normalized match length (0 == MIN_MATCH) */
var base_length = new Array(LENGTH_CODES);
zero(base_length);
/* First normalized length for each code (0 = MIN_MATCH) */
var base_dist = new Array(D_CODES);
zero(base_dist);
/* First normalized distance for each code (0 = distance of 1) */
function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) {
this.static_tree = static_tree; /* static tree or NULL */
this.extra_bits = extra_bits; /* extra bits for each code or NULL */
this.extra_base = extra_base; /* base index for extra_bits */
this.elems = elems; /* max number of elements in the tree */
this.max_length = max_length; /* max bit length for the codes */
// show if `static_tree` has data or dummy - needed for monomorphic objects
this.has_stree = static_tree && static_tree.length;
}
var static_l_desc;
var static_d_desc;
var static_bl_desc;
function TreeDesc(dyn_tree, stat_desc) {
this.dyn_tree = dyn_tree; /* the dynamic tree */
this.max_code = 0; /* largest code with non zero frequency */
this.stat_desc = stat_desc; /* the corresponding static tree */
}
function d_code(dist) {
return dist >> 7)];
}
/* ===========================================================================
* Output a short LSB first on the stream.
* IN assertion: there is enough room in pendingBuf.
*/
function put_short(s, w) {
// put_byte(s, (uch)((w) & 0xff));
// put_byte(s, (uch)((ush)(w) >> 8));
s.pending_buf[s.pending++] = (w) & 0xff;
s.pending_buf[s.pending++] = (w >>> 8) & 0xff;
}
/* ===========================================================================
* Send a value on a given number of bits.
* IN assertion: length (Buf_size - length)) {
s.bi_buf |= (value > (Buf_size - s.bi_valid);
s.bi_valid += length - Buf_size;
} else {
s.bi_buf |= (value >>= 1;
res 0);
return res >>> 1;
}
/* ===========================================================================
* Flush the bit buffer, keeping at most 7 bits in it.
*/
function bi_flush(s) {
if (s.bi_valid === 16) {
put_short(s, s.bi_buf);
s.bi_buf = 0;
s.bi_valid = 0;
} else if (s.bi_valid >= 8) {
s.pending_buf[s.pending++] = s.bi_buf & 0xff;
s.bi_buf >>= 8;
s.bi_valid -= 8;
}
}
/* ===========================================================================
* Compute the optimal bit lengths for a tree and update the total bit length
* for the current block.
* IN assertion: the fields freq and dad are set, heap[heap_max] and
* above are the tree nodes sorted by increasing frequency.
* OUT assertions: the field len is set to the optimal bit length, the
* array bl_count contains the frequencies for each bit length.
* The length opt_len is updated; static_len is also updated if stree is
* not null.
*/
function gen_bitlen(s, desc)
// deflate_state *s;
// tree_desc *desc; /* the tree descriptor */
{
var tree = desc.dyn_tree;
var max_code = desc.max_code;
var stree = desc.stat_desc.static_tree;
var has_stree = desc.stat_desc.has_stree;
var extra = desc.stat_desc.extra_bits;
var base = desc.stat_desc.extra_base;
var max_length = desc.stat_desc.max_length;
var h; /* heap index */
var n, m; /* iterate over the tree elements */
var bits; /* bit length */
var xbits; /* extra bits */
var f; /* frequency */
var overflow = 0; /* number of elements with bit length too large */
for (bits = 0; bits max_length) {
bits = max_length;
overflow++;
}
tree[n * 2 + 1]/*.Len*/ = bits;
/* We overwrite tree[n].Dad which is no longer needed */
if (n > max_code) { continue; } /* not a leaf node */
s.bl_count[bits]++;
xbits = 0;
if (n >= base) {
xbits = extra[n - base];
}
f = tree[n * 2]/*.Freq*/;
s.opt_len += f * (bits + xbits);
if (has_stree) {
s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits);
}
}
if (overflow === 0) { return; }
// Trace((stderr,"\nbit length overflow\n"));
/* This happens for example on obj2 and pic of the Calgary corpus */
/* Find the first bit length which could increase: */
do {
bits = max_length - 1;
while (s.bl_count[bits] === 0) { bits--; }
s.bl_count[bits]--; /* move one leaf down the tree */
s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */
s.bl_count[max_length]--;
/* The brother of the overflow item also moves one step up,
* but this does not affect bl_count[max_length]
*/
overflow -= 2;
} while (overflow > 0);
/* Now recompute all bit lengths, scanning in increasing frequency.
* h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
* lengths instead of fixing only the wrong ones. This idea is taken
* from 'ar' written by Haruhiko Okumura.)
*/
for (bits = max_length; bits !== 0; bits--) {
n = s.bl_count[bits];
while (n !== 0) {
m = s.heap[--h];
if (m > max_code) { continue; }
if (tree[m * 2 + 1]/*.Len*/ !== bits) {
// Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/;
tree[m * 2 + 1]/*.Len*/ = bits;
}
n--;
}
}
}
/* ===========================================================================
* Generate the codes for a given tree and bit counts (which need not be
* optimal).
* IN assertion: the array bl_count contains the bit length statistics for
* the given tree and the field len is set for all tree elements.
* OUT assertion: the field code is set for all tree elements of non
* zero code length.
*/
function gen_codes(tree, max_code, bl_count)
// ct_data *tree; /* the tree to decorate */
// int max_code; /* largest code with non zero frequency */
// ushf *bl_count; /* number of codes at each bit length */
{
var next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */
var code = 0; /* running code value */
var bits; /* bit index */
var n; /* code index */
/* The distribution counts are first used to generate the code values
* without bit reversal.
*/
for (bits = 1; bits length code (0..28) */
length = 0;
for (code = 0; code dist code (0..29) */
dist = 0;
for (code = 0; code >= 7; /* from now on, all distances are divided by 128 */
for (; code 8) {
put_short(s, s.bi_buf);
} else if (s.bi_valid > 0) {
//put_byte(s, (Byte)s->bi_buf);
s.pending_buf[s.pending++] = s.bi_buf;
}
s.bi_buf = 0;
s.bi_valid = 0;
}
/* ===========================================================================
* Copy a stored block, storing first the length and its
* one's complement if requested.
*/
function copy_block(s, buf, len, header)
//DeflateState *s;
//charf *buf; /* the input data */
//unsigned len; /* its length */
//int header; /* true if block header must be written */
{
bi_windup(s); /* align on byte boundary */
if (header) {
put_short(s, len);
put_short(s, ~len);
}
// while (len--) {
// put_byte(s, *buf++);
// }
utils.arraySet(s.pending_buf, s.window, buf, len, s.pending);
s.pending += len;
}
/* ===========================================================================
* Compares to subtrees, using the tree depth as tie breaker when
* the subtrees have equal frequency. This minimizes the worst case length.
*/
function smaller(tree, n, m, depth) {
var _n2 = n * 2;
var _m2 = m * 2;
return (tree[_n2]/*.Freq*/ pending) lit_bufsize + 2*lx,
// "pendingBuf overflow");
} while (lx > 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); }
/* Construct the Huffman tree by repeatedly combining the least two
* frequent nodes.
*/
node = elems; /* next internal node of the tree */
do {
//pqremove(s, tree, n); /* n = node of least frequency */
/*** pqremove ***/
n = s.heap[1/*SMALLEST*/];
s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--];
pqdownheap(s, tree, 1/*SMALLEST*/);
/***/
m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */
s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */
s.heap[--s.heap_max] = m;
/* Create a new node father of n and m */
tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/;
s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1;
tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node;
/* and insert the new node in the heap */
s.heap[1/*SMALLEST*/] = node++;
pqdownheap(s, tree, 1/*SMALLEST*/);
} while (s.heap_len >= 2);
s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/];
/* At this point, the fields freq and dad are set. We can now
* generate the bit lengths.
*/
gen_bitlen(s, desc);
/* The field len is now set, we can generate the bit codes */
gen_codes(tree, max_code, s.bl_count);
}
/* ===========================================================================
* Scan a literal or distance tree to determine the frequencies of the codes
* in the bit length tree.
*/
function scan_tree(s, tree, max_code)
// deflate_state *s;
// ct_data *tree; /* the tree to be scanned */
// int max_code; /* and its largest code of non zero frequency */
{
var n; /* iterates over all tree elements */
var prevlen = -1; /* last emitted length */
var curlen; /* length of current code */
var nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */
var count = 0; /* repeat count of the current code */
var max_count = 7; /* max repeat count */
var min_count = 4; /* min repeat count */
if (nextlen === 0) {
max_count = 138;
min_count = 3;
}
tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */
for (n = 0; n = 3 && count = 3; max_blindex--) {
if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) {
break;
}
}
/* Update opt_len to include the bit length tree and counts */
s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
//Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
// s->opt_len, s->static_len));
return max_blindex;
}
/* ===========================================================================
* Send the header for a block using dynamic Huffman trees: the counts, the
* lengths of the bit length codes, the literal tree and the distance tree.
* IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
*/
function send_all_trees(s, lcodes, dcodes, blcodes)
// deflate_state *s;
// int lcodes, dcodes, blcodes; /* number of codes for each tree */
{
var rank; /* index in bl_order */
//Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
//Assert (lcodes bits_sent));
send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */
//Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */
//Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
}
/* ===========================================================================
* Check if the data type is TEXT or BINARY, using the following algorithm:
* - TEXT if the two conditions below are satisfied:
* a) There are no non-portable control characters belonging to the
* "black list" (0..6, 14..25, 28..31).
* b) There is at least one printable character belonging to the
* "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
* - BINARY otherwise.
* - The following partially-portable control characters form a
* "gray list" that is ignored in this detection algorithm:
* (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
* IN assertion: the fields Freq of dyn_ltree are set.
*/
function detect_data_type(s) {
/* black_mask is the bit mask of black-listed bytes
* set bits 0..6, 14..25, and 28..31
* 0xf3ffc07f = binary 11110011111111111100000001111111
*/
var black_mask = 0xf3ffc07f;
var n;
/* Check for non-textual ("black-listed") bytes. */
for (n = 0; n >>= 1) {
if ((black_mask & 1) && (s.dyn_ltree[n * 2]/*.Freq*/ !== 0)) {
return Z_BINARY;
}
}
/* Check for textual ("white-listed") bytes. */
if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 ||
s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) {
return Z_TEXT;
}
for (n = 32; n 0) {
/* Check if the file is binary or text */
if (s.strm.data_type === Z_UNKNOWN) {
s.strm.data_type = detect_data_type(s);
}
/* Construct the literal and distance trees */
build_tree(s, s.l_desc);
// Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
// s->static_len));
build_tree(s, s.d_desc);
// Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
// s->static_len));
/* At this point, opt_len and static_len are the total bit lengths of
* the compressed block data, excluding the tree representations.
*/
/* Build the bit length tree for the above two trees, and get the index
* in bl_order of the last bit length code to send.
*/
max_blindex = build_bl_tree(s);
/* Determine the best encoding. Compute the block lengths in bytes. */
opt_lenb = (s.opt_len + 3 + 7) >>> 3;
static_lenb = (s.static_len + 3 + 7) >>> 3;
// Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
// opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
// s->last_lit));
if (static_lenb WSIZE.
* Otherwise we can't have processed more than WSIZE input bytes since
* the last block flush, because compression would have been
* successful. If LIT_BUFSIZE compressed_len == s->bits_sent, "bad compressed size");
/* The above check is made mod 2^32, for files larger than 512 MB
* and uLong implemented on 32 bits.
*/
init_block(s);
if (last) {
bi_windup(s);
}
// Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
// s->compressed_len-7*last));
}
/* ===========================================================================
* Save the match info and tally the frequency counts. Return true if
* the current block must be flushed.
*/
function _tr_tally(s, dist, lc)
// deflate_state *s;
// unsigned dist; /* distance of matched string */
// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
{
//var out_length, in_length, dcode;
s.pending_buf[s.d_buf + s.last_lit * 2] = (dist >>> 8) & 0xff;
s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff;
s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff;
s.last_lit++;
if (dist === 0) {
/* lc is the unmatched char */
s.dyn_ltree[lc * 2]/*.Freq*/++;
} else {
s.matches++;
/* Here, lc is the match length - MIN_MATCH */
dist--; /* dist = match distance - 1 */
//Assert((ush)dist 2) {
// /* Compute an upper bound for the compressed length */
// out_length = s.last_lit*8;
// in_length = s.strstart - s.block_start;
//
// for (dcode = 0; dcode >>= 3;
// //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
// // s->last_lit, in_length, out_length,
// // 100L - out_length*100L/in_length));
// if (s.matches >1)/*int /2*/ && out_length >1)/*int /2*/) {
// return true;
// }
// }
//#endif
return (s.last_lit === s.lit_bufsize - 1);
/* We avoid equality with lit_bufsize because of wraparound at 64K
* on 16 bit machines and because stored blocks are restricted to
* 64K-1 bytes.
*/
}
exports._tr_init = _tr_init;
exports._tr_stored_block = _tr_stored_block;
exports._tr_flush_block = _tr_flush_block;
exports._tr_tally = _tr_tally;
exports._tr_align = _tr_align;
},{"../utils/common":41}],53:[function(require,module,exports){
'use strict';
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
function ZStream() {
/* next input byte */
this.input = null; // JS specific, because we have no pointers
this.next_in = 0;
/* number of bytes available at input */
this.avail_in = 0;
/* total number of input bytes read so far */
this.total_in = 0;
/* next output byte should be put there */
this.output = null; // JS specific, because we have no pointers
this.next_out = 0;
/* remaining free space at output */
this.avail_out = 0;
/* total number of bytes output so far */
this.total_out = 0;
/* last error message, NULL if no error */
this.msg = ''/*Z_NULL*/;
/* not visible by applications */
this.state = null;
/* best guess about the data type: binary or text */
this.data_type = 2/*Z_UNKNOWN*/;
/* adler32 value of the uncompressed data */
this.adler = 0;
}
module.exports = ZStream;
},{}],54:[function(require,module,exports){
'use strict';
module.exports = typeof setImmediate === 'function' ? setImmediate :
function setImmediate() {
var args = [].slice.apply(arguments);
args.splice(1, 0, 0);
setTimeout.apply(null, args);
};
},{}]},{},[10])(10)
});
/*!
* screenfull
* v5.0.2 - 2020-02-13
* (c) Sindre Sorhus; MIT License
*/
(function () {
'use strict';
var document = typeof window !== 'undefined' && typeof window.document !== 'undefined' ? window.document : {};
var isCommonjs = typeof module !== 'undefined' && module.exports;
var fn = (function () {
var val;
var fnMap = [
[
'requestFullscreen',
'exitFullscreen',
'fullscreenElement',
'fullscreenEnabled',
'fullscreenchange',
'fullscreenerror'
],
// New WebKit
[
'webkitRequestFullscreen',
'webkitExitFullscreen',
'webkitFullscreenElement',
'webkitFullscreenEnabled',
'webkitfullscreenchange',
'webkitfullscreenerror'
],
// Old WebKit
[
'webkitRequestFullScreen',
'webkitCancelFullScreen',
'webkitCurrentFullScreenElement',
'webkitCancelFullScreen',
'webkitfullscreenchange',
'webkitfullscreenerror'
],
[
'mozRequestFullScreen',
'mozCancelFullScreen',
'mozFullScreenElement',
'mozFullScreenEnabled',
'mozfullscreenchange',
'mozfullscreenerror'
],
[
'msRequestFullscreen',
'msExitFullscreen',
'msFullscreenElement',
'msFullscreenEnabled',
'MSFullscreenChange',
'MSFullscreenError'
]
];
var i = 0;
var l = fnMap.length;
var ret = {};
for (; i postsJSON
values[1] // => commentsJSON
return values;
});
```
@class RSVP.Promise
@param {function} resolver
@param {String} label optional string for labeling the promise.
Useful for tooling.
@constructor
*/
var Promise = function () {
function Promise(resolver, label) {
this._id = counter++;
this._label = label;
this._state = undefined;
this._result = undefined;
this._subscribers = [];
config.instrument && instrument('created', this);
if (noop !== resolver) {
typeof resolver !== 'function' && needsResolver();
this instanceof Promise ? initializePromise(this, resolver) : needsNew();
}
}
Promise.prototype._onError = function _onError(reason) {
var _this = this;
config.after(function () {
if (_this._onError) {
config.trigger('error', reason, _this._label);
}
});
};
/**
`catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
as the catch block of a try/catch statement.
```js
function findAuthor(){
throw new Error('couldn\'t find that author');
}
// synchronous
try {
findAuthor();
} catch(reason) {
// something went wrong
}
// async with promises
findAuthor().catch(function(reason){
// something went wrong
});
```
@method catch
@param {Function} onRejection
@param {String} label optional string for labeling the promise.
Useful for tooling.
@return {Promise}
*/
Promise.prototype.catch = function _catch(onRejection, label) {
return this.then(undefined, onRejection, label);
};
/**
`finally` will be invoked regardless of the promise's fate just as native
try/catch/finally behaves
Synchronous example:
```js
findAuthor() {
if (Math.random() > 0.5) {
throw new Error();
}
return new Author();
}
try {
return findAuthor(); // succeed or fail
} catch(error) {
return findOtherAuthor();
} finally {
// always runs
// doesn't affect the return value
}
```
Asynchronous example:
```js
findAuthor().catch(function(reason){
return findOtherAuthor();
}).finally(function(){
// author was either found, or not
});
```
@method finally
@param {Function} callback
@param {String} label optional string for labeling the promise.
Useful for tooling.
@return {Promise}
*/
Promise.prototype.finally = function _finally(callback, label) {
var promise = this;
var constructor = promise.constructor;
return promise.then(function (value) {
return constructor.resolve(callback()).then(function () {
return value;
});
}, function (reason) {
return constructor.resolve(callback()).then(function () {
throw reason;
});
}, label);
};
return Promise;
}();
Promise.cast = resolve$1; // deprecated
Promise.all = all;
Promise.race = race;
Promise.resolve = resolve$1;
Promise.reject = reject$1;
Promise.prototype._guidKey = guidKey;
/**
The primary way of interacting with a promise is through its `then` method,
which registers callbacks to receive either a promise's eventual value or the
reason why the promise cannot be fulfilled.
```js
findUser().then(function(user){
// user is available
}, function(reason){
// user is unavailable, and you are given the reason why
});
```
Chaining
--------
The return value of `then` is itself a promise. This second, 'downstream'
promise is resolved with the return value of the first promise's fulfillment
or rejection handler, or rejected if the handler throws an exception.
```js
findUser().then(function (user) {
return user.name;
}, function (reason) {
return 'default name';
}).then(function (userName) {
// If `findUser` fulfilled, `userName` will be the user's name, otherwise it
// will be `'default name'`
});
findUser().then(function (user) {
throw new Error('Found user, but still unhappy');
}, function (reason) {
throw new Error('`findUser` rejected and we\'re unhappy');
}).then(function (value) {
// never reached
}, function (reason) {
// if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
// If `findUser` rejected, `reason` will be '`findUser` rejected and we\'re unhappy'.
});
```
If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
```js
findUser().then(function (user) {
throw new PedagogicalException('Upstream error');
}).then(function (value) {
// never reached
}).then(function (value) {
// never reached
}, function (reason) {
// The `PedgagocialException` is propagated all the way down to here
});
```
Assimilation
------------
Sometimes the value you want to propagate to a downstream promise can only be
retrieved asynchronously. This can be achieved by returning a promise in the
fulfillment or rejection handler. The downstream promise will then be pending
until the returned promise is settled. This is called *assimilation*.
```js
findUser().then(function (user) {
return findCommentsByAuthor(user);
}).then(function (comments) {
// The user's comments are now available
});
```
If the assimliated promise rejects, then the downstream promise will also reject.
```js
findUser().then(function (user) {
return findCommentsByAuthor(user);
}).then(function (comments) {
// If `findCommentsByAuthor` fulfills, we'll have the value here
}, function (reason) {
// If `findCommentsByAuthor` rejects, we'll have the reason here
});
```
Simple Example
--------------
Synchronous Example
```javascript
let result;
try {
result = findResult();
// success
} catch(reason) {
// failure
}
```
Errback Example
```js
findResult(function(result, err){
if (err) {
// failure
} else {
// success
}
});
```
Promise Example;
```javascript
findResult().then(function(result){
// success
}, function(reason){
// failure
});
```
Advanced Example
--------------
Synchronous Example
```javascript
let author, books;
try {
author = findAuthor();
books = findBooksByAuthor(author);
// success
} catch(reason) {
// failure
}
```
Errback Example
```js
function foundBooks(books) {
}
function failure(reason) {
}
findAuthor(function(author, err){
if (err) {
failure(err);
// failure
} else {
try {
findBoooksByAuthor(author, function(books, err) {
if (err) {
failure(err);
} else {
try {
foundBooks(books);
} catch(reason) {
failure(reason);
}
}
});
} catch(error) {
failure(err);
}
// success
}
});
```
Promise Example;
```javascript
findAuthor().
then(findBooksByAuthor).
then(function(books){
// found books
}).catch(function(reason){
// something went wrong
});
```
@method then
@param {Function} onFulfillment
@param {Function} onRejection
@param {String} label optional string for labeling the promise.
Useful for tooling.
@return {Promise}
*/
Promise.prototype.then = then;
function Result() {
this.value = undefined;
}
var ERROR = new Result();
var GET_THEN_ERROR$1 = new Result();
function getThen$1(obj) {
try {
return obj.then;
} catch (error) {
ERROR.value = error;
return ERROR;
}
}
function tryApply(f, s, a) {
try {
f.apply(s, a);
} catch (error) {
ERROR.value = error;
return ERROR;
}
}
function makeObject(_, argumentNames) {
var obj = {};
var length = _.length;
var args = new Array(length);
for (var x = 0; x res
// result[1] -> body
});
```
Or if you pass it an array with names it returns the parameters as a hash:
```javascript
let request = RSVP.denodeify(require('request'), ['res', 'body']);
request('http://example.com').then(function(result) {
// result.res
// result.body
});
```
Sometimes you need to retain the `this`:
```javascript
let app = require('express')();
let render = RSVP.denodeify(app.render.bind(app));
```
The denodified function inherits from the original function. It works in all
environments, except IE 10 and below. Consequently all properties of the original
function are available to you. However, any properties you change on the
denodeified function won't be changed on the original function. Example:
```javascript
let request = RSVP.denodeify(require('request')),
cookieJar = request.jar(); // 2 && arguments[2] !== undefined ? arguments[2] : true;
var label = arguments[3];
return _possibleConstructorReturn$1(this, _Enumerator.call(this, Constructor, object, abortOnReject, label));
}
PromiseHash.prototype._init = function _init(Constructor, object) {
this._result = {};
this._enumerate(object);
if (this._remaining === 0) {
fulfill(this.promise, this._result);
}
};
PromiseHash.prototype._enumerate = function _enumerate(input) {
var promise = this.promise;
var results = [];
for (var key in input) {
if (hasOwnProperty.call(input, key)) {
results.push({
position: key,
entry: input[key]
});
}
}
var length = results.length;
this._remaining = length;
var result = void 0;
for (var i = 0; promise._state === PENDING && i 1;
};
RSVP.filter(promises, filterFn).then(function(result){
// result is [ 2, 3 ]
});
```
If any of the `promises` given to `RSVP.filter` are rejected, the first promise
that is rejected will be given as an argument to the returned promise's
rejection handler. For example:
```javascript
let promise1 = RSVP.resolve(1);
let promise2 = RSVP.reject(new Error('2'));
let promise3 = RSVP.reject(new Error('3'));
let promises = [ promise1, promise2, promise3 ];
let filterFn = function(item){
return item > 1;
};
RSVP.filter(promises, filterFn).then(function(array){
// Code here never runs because there are rejected promises!
}, function(reason) {
// reason.message === '2'
});
```
`RSVP.filter` will also wait for any promises returned from `filterFn`.
For instance, you may want to fetch a list of users then return a subset
of those users based on some asynchronous operation:
```javascript
let alice = { name: 'alice' };
let bob = { name: 'bob' };
let users = [ alice, bob ];
let promises = users.map(function(user){
return RSVP.resolve(user);
});
let filterFn = function(user){
// Here, Alice has permissions to create a blog post, but Bob does not.
return getPrivilegesForUser(user).then(function(privs){
return privs.can_create_blog_post === true;
});
};
RSVP.filter(promises, filterFn).then(function(users){
// true, because the server told us only Alice can create a blog post.
users.length === 1;
// false, because Alice is the only user present in `users`
users[0] === bob;
});
```
@method filter
@static
@for RSVP
@param {Array} promises
@param {Function} filterFn - function to be called on each resolved value to
filter the final results.
@param {String} label optional string describing the promise. Useful for
tooling.
@return {Promise}
*/
function resolveAll(promises, label) {
return Promise.all(promises, label);
}
function resolveSingle(promise, label) {
return Promise.resolve(promise, label).then(function (promises) {
return resolveAll(promises, label);
});
}
function filter(promises, filterFn, label) {
if (!isArray(promises) && !(isObject(promises) && promises.then !== undefined)) {
return Promise.reject(new TypeError("RSVP.filter must be called with an array or promise"), label);
}
if (!isFunction(filterFn)) {
return Promise.reject(new TypeError("RSVP.filter expects function as a second argument"), label);
}
var promise = isArray(promises) ? resolveAll(promises, label) : resolveSingle(promises, label);
return promise.then(function (values) {
var length = values.length;
var filtered = new Array(length);
for (var i = 0; i b) return 1;
if(a 0 ? pivot : pivot + 1;
}
if(compared === 0) {
return pivot;
}
if(compared === -1) {
return EPUBJS.core.locationOf(item, array, compareFunction, pivot, end);
} else{
return EPUBJS.core.locationOf(item, array, compareFunction, start, pivot);
}
};
EPUBJS.core.indexOfSorted = function(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 -1 ) return;
this.settings.bookmarks.push(cfi);
this.trigger("reader:bookmarked", cfi);
};
EPUBJS.Reader.prototype.removeBookmark = function(cfi) {
var bookmark = this.isBookmarked(cfi);
if( bookmark === -1 ) return;
this.settings.bookmarks.splice(bookmark, 1);
this.trigger("reader:unbookmarked", bookmark);
};
EPUBJS.Reader.prototype.isBookmarked = function(cfi) {
var bookmarks = this.settings.bookmarks;
return bookmarks.indexOf(cfi);
};
/*
EPUBJS.Reader.prototype.searchBookmarked = function(cfi) {
var bookmarks = this.settings.bookmarks,
len = bookmarks.length,
i;
for(i = 0; i iheight / 2.5) {
maxHeight = iheight / 2.5;
pop_content.style.maxHeight = maxHeight + "px";
}
//-- switch above / below
if(popRect.height + top >= iheight - 25) {
pop.style.top = top - popRect.height + "px";
pop.classList.add("above");
}else{
pop.classList.remove("above");
}
//-- switch left
if(left - popRect.width = iwidth) {
//-- TEMP MOVE: 300
pop.style.left = left - 300 + "px";
popRect = pop.getBoundingClientRect();
pop.style.left = left - popRect.width + "px";
//-- switch above / below again
if(popRect.height + top >= iheight - 25) {
pop.style.top = top - popRect.height + "px";
pop.classList.add("above");
}else{
pop.classList.remove("above");
}
pop.classList.add("right");
}else{
pop.classList.remove("right");
}
}
var onPop = function(){
popups[id].classList.add("on");
}
var offPop = function(){
popups[id].classList.remove("on");
}
var hidePop = function(){
setTimeout(function(){
popups[id].classList.remove("show");
}, 100);
}
var openSidebar = function(){
reader.ReaderController.slideOut();
show();
};
item.addEventListener("mouseover", showPop, false);
item.addEventListener("mouseout", hidePop, false);
item.addEventListener("click", openSidebar, false);
}
$anchor.on("click", function(e){
$anchor.text("Cancel");
$text.prop("disabled", "true");
// listen for selection
rendition.on("click", insertAtPoint);
});
annotations.forEach(function(note) {
addAnnotation(note);
});
/*
renderer.registerHook("beforeChapterDisplay", function(callback, renderer){
var chapter = renderer.currentChapter;
annotations.forEach(function(note) {
var cfi = epubcfi.parse(note.anchor);
if(cfi.spinePos === chapter.spinePos) {
try {
placeMarker(note);
} catch(e) {
console.log("anchoring failed", note.anchor);
}
}
});
callback();
}, true);
*/
return {
"show" : show,
"hide" : hide
};
};
EPUBJS.reader.ReaderController = function(book) {
var $main = $("#main"),
$divider = $("#divider"),
$loader = $("#loader"),
$next = $("#next"),
$prev = $("#prev");
var reader = this;
var book = this.book;
var rendition = this.rendition;
var slideIn = function() {
var currentPosition = rendition.currentLocation().start.cfi;
if (reader.settings.sidebarReflow){
$main.removeClass('single');
$main.one("transitionend", function(){
rendition.resize();
});
} else {
$main.removeClass("closed");
}
};
var slideOut = function() {
var location = rendition.currentLocation();
if (!location) {
return;
}
var currentPosition = location.start.cfi;
if (reader.settings.sidebarReflow){
$main.addClass('single');
$main.one("transitionend", function(){
rendition.resize();
});
} else {
$main.addClass("closed");
}
};
var showLoader = function() {
$loader.show();
hideDivider();
};
var hideLoader = function() {
$loader.hide();
//-- If the book is using spreads, show the divider
// if(book.settings.spreads) {
// showDivider();
// }
};
var showDivider = function() {
$divider.addClass("show");
};
var hideDivider = function() {
$divider.removeClass("show");
};
var keylock = false;
var arrowKeys = function(e) {
if(e.keyCode == 37) {
if(book.package.metadata.direction === "rtl") {
rendition.next();
} else {
rendition.prev();
}
$prev.addClass("active");
keylock = true;
setTimeout(function(){
keylock = false;
$prev.removeClass("active");
}, 100);
e.preventDefault();
}
if(e.keyCode == 39) {
if(book.package.metadata.direction === "rtl") {
rendition.prev();
} else {
rendition.next();
}
$next.addClass("active");
keylock = true;
setTimeout(function(){
keylock = false;
$next.removeClass("active");
}, 100);
e.preventDefault();
}
}
document.addEventListener('keydown', arrowKeys, false);
$next.on("click", function(e){
if(book.package.metadata.direction === "rtl") {
rendition.prev();
} else {
rendition.next();
}
e.preventDefault();
});
$prev.on("click", function(e){
if(book.package.metadata.direction === "rtl") {
rendition.next();
} else {
rendition.prev();
}
e.preventDefault();
});
rendition.on("layout", function(props){
if(props.spread === true) {
showDivider();
} else {
hideDivider();
}
});
rendition.on('relocated', function(location){
if (location.atStart) {
$prev.addClass("disabled");
}
if (location.atEnd) {
$next.addClass("disabled");
}
});
return {
"slideOut" : slideOut,
"slideIn" : slideIn,
"showLoader" : showLoader,
"hideLoader" : hideLoader,
"showDivider" : showDivider,
"hideDivider" : hideDivider,
"arrowKeys" : arrowKeys
};
};
EPUBJS.reader.SettingsController = function() {
var book = this.book;
var reader = this;
var $settings = $("#settings-modal"),
$overlay = $(".overlay");
var show = function() {
$settings.addClass("md-show");
};
var hide = function() {
$settings.removeClass("md-show");
};
var $sidebarReflowSetting = $('#sidebarReflow');
$sidebarReflowSetting.on('click', function() {
reader.settings.sidebarReflow = !reader.settings.sidebarReflow;
});
$settings.find(".closer").on("click", function() {
hide();
});
$overlay.on("click", function() {
hide();
});
return {
"show" : show,
"hide" : hide
};
};
EPUBJS.reader.SidebarController = function(book) {
var reader = this;
var $sidebar = $("#sidebar"),
$panels = $("#panels");
var activePanel = "Toc";
var changePanelTo = function(viewName) {
var controllerName = viewName + "Controller";
if(activePanel == viewName || typeof reader[controllerName] === 'undefined' ) return;
reader[activePanel+ "Controller"].hide();
reader[controllerName].show();
activePanel = viewName;
$panels.find('.active').removeClass("active");
$panels.find("#show-" + viewName ).addClass("active");
};
var getActivePanel = function() {
return activePanel;
};
var show = function() {
reader.sidebarOpen = true;
reader.ReaderController.slideOut();
$sidebar.addClass("open");
}
var hide = function() {
reader.sidebarOpen = false;
reader.ReaderController.slideIn();
$sidebar.removeClass("open");
}
$panels.find(".show_view").on("click", function(event) {
var view = $(this).data("view");
changePanelTo(view);
event.preventDefault();
});
return {
'show' : show,
'hide' : hide,
'getActivePanel' : getActivePanel,
'changePanelTo' : changePanelTo
};
};
EPUBJS.reader.TocController = function(toc) {
var book = this.book;
var rendition = this.rendition;
var $list = $("#tocView"),
docfrag = document.createDocumentFragment();
var currentChapter = false;
var generateTocItems = function(toc, level) {
var container = document.createElement("ul");
if(!level) level = 1;
toc.forEach(function(chapter) {
var listitem = document.createElement("li"),
link = document.createElement("a");
toggle = document.createElement("a");
var subitems;
listitem.id = "toc-"+chapter.id;
listitem.classList.add('list_item');
link.textContent = chapter.label;
link.href = chapter.href;
link.classList.add('toc_link');
listitem.appendChild(link);
if(chapter.subitems && chapter.subitems.length > 0) {
level++;
subitems = generateTocItems(chapter.subitems, level);
toggle.classList.add('toc_toggle');
listitem.insertBefore(toggle, link);
listitem.appendChild(subitems);
}
container.appendChild(listitem);
});
return container;
};
var onShow = function() {
$list.show();
};
var onHide = function() {
$list.hide();
};
var chapterChange = function(e) {
var id = e.id,
$item = $list.find("#toc-"+id),
$current = $list.find(".currentChapter"),
$open = $list.find('.openChapter');
if($item.length){
if($item != $current && $item.has(currentChapter).length > 0) {
$current.removeClass("currentChapter");
}
$item.addClass("currentChapter");
// $open.removeClass("openChapter");
$item.parents('li').addClass("openChapter");
}
};
rendition.on('renderered', chapterChange);
var tocitems = generateTocItems(toc);
docfrag.appendChild(tocitems);
$list.append(docfrag);
$list.find(".toc_link").on("click", function(event){
var url = this.getAttribute('href');
event.preventDefault();
//-- Provide the Book with the url to show
// The Url must be found in the books manifest
rendition.display(url);
$list.find(".currentChapter")
.addClass("openChapter")
.removeClass("currentChapter");
$(this).parent('li').addClass("currentChapter");
});
$list.find(".toc_toggle").on("click", function(event){
var $el = $(this).parent('li'),
open = $el.hasClass("openChapter");
event.preventDefault();
if(open){
$el.removeClass("openChapter");
} else {
$el.addClass("openChapter");
}
});
return {
"show" : onShow,
"hide" : onHide
};
};
//# sourceMappingURL=reader.js.map
/*
* twan: print EPUB
*/
$(function() {
var $print = $("#print");
$print.on("click", function() {
$("#viewer iframe").each(function (index, value){
var iframe = value;
// remove EPUB reader's styles which makes content flow from left to right
iframe.contentDocument.body.setAttribute("style", "");
var printStyle = iframe.contentDocument.getElementById('epub-reader-print-style');
if (printStyle === null) {
// insert print style
var css = iframe.contentDocument.createElement("style");
css.setAttribute("type", "text/css");
css.setAttribute("id", "epub-reader-print-style");
// set page margin, works for FF, Chrome, but not Safari
css.textContent = "@page {margin: 2cm;}";
iframe.contentDocument.head.appendChild(css);
}
iframe.contentWindow.focus();
iframe.contentWindow.print();
});
});
});
/*
* twan: plugin that searches entire EPUB using epubjs
* Origin: https://github.com/futurepress/epub.js/blob/v0.2/reader/js/plugins/search.js
* Updated by twan based on https://github.com/futurepress/epub.js/wiki/Tips-and-Tricks-%28v0.3%29
* Updated by jstegmaier to be ES5/IE11 compatible, including add the "finally" polyfil
*/
if(Promise.prototype.finally == null){
Promise.prototype.finally = function(fn) {
const onFinally = function(callback){
return Promise.resolve(fn()).then(callback);
};
return this.then(
function(result){
return onFinally(function(){ return result;});
},
function(reason){
return onFinally(function(){return Promise.reject(reason)});
}
);
};
}
EPUBJS.reader.search = {};
EPUBJS.reader.search.request = function(book, q, callback) {
results = Promise.all(
book.spine.spineItems.map(function(item){
return item.load(book.load.bind(book)).then(item.find.bind(item, q)).finally(item.unload.bind(item));
})
).then(function(results){
return Promise.resolve([].concat.apply([], results));
});
results.then(function(value) {
callback(value);
});
};
EPUBJS.reader.plugins.SearchController = function(book) {
var reader = this;
var $searchBox = $("#searchBox"),
$searchResults = $("#searchResults"),
$searchView = $("#searchView"),
iframeDoc;
var onShow = function() {
$searchView.addClass("shown");
};
var onHide = function() {
$searchView.removeClass("shown");
};
var highlight = function() {
var q = $searchBox.val();
iframeDoc = $("#viewer iframe")[0].contentDocument;
$(iframeDoc).find('body').highlight(q, { style: 'background-color: yellow' });
}
var query = function() {
var q = $searchBox.val();
if(q == '') {
return;
}
$searchResults.empty();
$searchResults.append("
Searching...
");
EPUBJS.reader.search.request(book, q, function(results) {
r = results;
$searchResults.empty();
if(iframeDoc) {
$(iframeDoc).find('body').unhighlight();
}
if(results.length == 0) {
$searchResults.append("
");
// search returns cfi range, example: epubcfi(/6/6[item33]!/4/102,/3:40,/3:45)
// We need to convert the cfi range to cfi: epubcfi(/6/6[item33]!/4/102/3)
var cfi = result.cfi.substr(0, result.cfi.indexOf(':')) + ")";
cfi = cfi.replace(",", "")
var $item = $(" "+result.excerpt+"");
$item.highlight(q);
$item.on("click", function(e) {
var cfi = this.getAttribute('href');
e.preventDefault();
book.rendition.display(cfi);
});
$li.append($item);
$searchResults.append($li);
});
});
};
// twan: Firefox doesn't support search event
// use change here instead of search
$searchBox.on("change", function(e) {
var q = $searchBox.val();
//-- SearchBox is empty or cleared
if(q == '') {
$searchResults.empty();
if(reader.SidebarController.getActivePanel() == "Search") {
reader.SidebarController.changePanelTo("Toc");
}
$(iframeDoc).find('body').unhighlight();
iframeDoc = false;
return;
}
reader.SidebarController.changePanelTo("Search");
query();
e.preventDefault();
});
return {
"show" : onShow,
"hide" : onHide
};
};
/*
* jQuery Highlight plugin
*
* Based on highlight v3 by Johann Burkard
* http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
*
* Code a little bit refactored and cleaned (in my humble opinion).
* Most important changes:
* - has an option to highlight only entire words (wordsOnly - false by default),
* - has an option to be case sensitive (caseSensitive - false by default)
* - highlight element tag and class names can be specified in options
*
* Usage:
* // wrap every occurrance of text 'lorem' in content
* // with (default options)
* $('#content').highlight('lorem');
*
* // search for and highlight more terms at once
* // so you can save some time on traversing DOM
* $('#content').highlight(['lorem', 'ipsum']);
* $('#content').highlight('lorem ipsum');
*
* // search only for entire word 'lorem'
* $('#content').highlight('lorem', { wordsOnly: true });
*
* // don't ignore case during search of term 'lorem'
* $('#content').highlight('lorem', { caseSensitive: true });
*
* // wrap every occurrance of term 'ipsum' in content
* // with
* $('#content').highlight('ipsum', { element: 'em', className: 'important' });
*
* // remove default highlight
* $('#content').unhighlight();
*
* // remove custom highlight
* $('#content').unhighlight({ element: 'em', className: 'important' });
*
*
* Copyright (c) 2009 Bartek Szopka
*
* Licensed under MIT license.
*
*/
/*
* twan: modified to include addtional setting: inline style
* This is useful when we have no control over CSS files
*
* // wrap every occurrance of text 'lorem' in content
* // with
* $('#content').highlight('lorem', { style: 'background-color: yellow' });
*/
jQuery.extend({
highlight: function (node, re, nodeName, className, style) {
if (node.nodeType === 3) {
var match = node.data.match(re);
if (match) {
var highlight = document.createElement(nodeName || 'span');
highlight.className = className || 'highlight';
highlight.style = style;
var wordNode = node.splitText(match.index);
wordNode.splitText(match[0].length);
var wordClone = wordNode.cloneNode(true);
highlight.appendChild(wordClone);
wordNode.parentNode.replaceChild(highlight, wordNode);
return 1; //skip added node in parent
}
} else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
!/(script|style)/i.test(node.tagName) && // ignore script and style nodes
!(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
for (var i = 0; i \n \n \n
\n\n\n\n\n';
viewerComponents['image'].onFirstLoad = function(container){
jQuery(function($){
var fulltext_visible = false,
supplement_data_visible = false;
$("#page-fulltext-toggle").live("click", function(event){
event.preventDefault();
if( $(event.target).parents('.imageviewer_text, .control-section-text').hasClass('enabled') ){
if( !fulltext_visible ){
setTimeout(function(){
$("#page-fulltext").show();
}, 500);
fulltext_visible = true;
}else{
$("#page-fulltext").hide();
fulltext_visible = false;
}
}
});
$("#page-data-toggle").live("click", function(event){
event.preventDefault();
if( $(event.target).parents('.imageviewer_text, .control-section-text').hasClass('enabled') ){
if( !supplement_data_visible ){
setTimeout(function(){
$("#page-data").fadeIn("slow");
}, 500);
supplement_data_visible = true;
}else{
$("#page-data").fadeOut("slow");
supplement_data_visible = false;
}
}
});
var currentPage = 1,
showReferenceStrip = false;
var tileSources = [],
resource = [
{
"height": 6757,
"info": "https://tile.loc.gov/image-services/iiif/service:ndnp:dlc:batch_dlc_abe_ver01:data:sn87062245:100492969:1902021401:0529/info.json",
"mimetype": "image/jp2",
"size": 4322336,
"url": "https://tile.loc.gov/storage-services/service/ndnp/dlc/batch_dlc_abe_ver01/data/sn87062245/100492969/1902021401/0529.jp2",
"use": "",
"width": 5115
},
{
"mimetype": "application/pdf",
"url": "https://tile.loc.gov/storage-services/service/ndnp/dlc/batch_dlc_abe_ver01/data/sn87062245/100492969/1902021401/0529.pdf",
"use": ""
},
{
"mimetype": "text/xml",
"url": "https://tile.loc.gov/storage-services/service/ndnp/dlc/batch_dlc_abe_ver01/data/sn87062245/100492969/1902021401/0529.xml",
"use": ""
},
{
"height": 422,
"levels": 1,
"mimetype": "image/jpeg",
"url": "https://tile.loc.gov/image-services/iiif/service:ndnp:dlc:batch_dlc_abe_ver01:data:sn87062245:100492969:1902021401:0529/full/pct:6.25/0/default.jpg",
"width": 319
},
{
"height": 844,
"levels": 1,
"mimetype": "image/jpeg",
"url": "https://tile.loc.gov/image-services/iiif/service:ndnp:dlc:batch_dlc_abe_ver01:data:sn87062245:100492969:1902021401:0529/full/pct:12.5/0/default.jpg",
"width": 639
},
{
"height": 6757,
"info": "https://tile.loc.gov/image-services/iiif/service:ndnp:dlc:batch_dlc_abe_ver01:data:sn87062245:100492969:1902021401:0529/info.json",
"language": [
"english"
],
"mimetype": "application/json",
"reel_number": "100492969",
"section_label": null,
"size": 4322336,
"title": "Image 1 of The Washington times (Washington [D.C.]), February 14, 1902",
"width": 5115
},
{
"fulltext_service": "https://tile.loc.gov/text-services//word-coordinates-service?segment=/service/ndnp/dlc/batch_dlc_abe_ver01/data/sn87062245/100492969/1902021401/0529.xml&format=alto_xml&full_text=1",
"mimetype": "text/plain",
"use": "text"
}
],
source,
i;
for( i = 0; i = 0; i--){
levels.push(i);
}
// For maps jp2 stuff:
// x,y is center of tile adjusted for scale
// level is 0 based and reversed compared to seadragon
var x1 = this.tileSize / this.getLevelScale( level ) * x,
y1 = this.tileSize / this.getLevelScale( level ) * y,
delta = ( this.tileSize / this.getLevelScale( level ) ) / 2;
return tileService + '?' +
'&data=' + jp2_file +
'&x=' + ( x1 + delta ) +
'&y=' + ( y1 + delta ) +
'&res=' + levels[ level ] +
'&width=' + this.tileSize +
'&height=' + this.tileSize +
'&jpegLevel=' + 80;
}
});
}
}
}
var viewer = new OpenSeadragon.Viewer({
id: 'viewer-image',
fullscreen_element: $('#viewer-image-wrapper')[0],
toolbar: 'viewer-toolbar',
prefixUrl: '/static/js/lib/openseadragon-2.3.1/images/',
showNavigator: false,
showReferenceStrip: false,
referenceStripScroll: 'vertical',
autoHideControls: false,
nextButton: 'next',
previousButton: 'previous',
zoomInButton: 'zoom-in',
zoomOutButton: 'zoom-out',
rotateRightButton: 'rotate-right',
homeButton: 'home',
fullPageButton: 'full-screen',
tileSources: tileSources,
preserveViewport: true,
onPageChange: function( data ){ }
});
/**
* Round a number to the specified decimal places
* If num is not a number then just return without changes
* @param num The number to be rounded
* @param decPlaces The number of decimal places to round to
* @returns number rounded to the specified number of decimal places
*/
var roundToDec = function(num, decPlaces){
if (num && !isNaN(num)){
// If num is able to be a number convert it to that
// Round it to a fixed decimal places (which returns a string)
// Convert back to a number
return Number(Number(num).toFixed(decPlaces));
} else {
return num;
}
};
/*
Go through the URL search query and remove the r=...
You do this you move/zoom the view in the animation finish
And when you take a clipping
*/
var removeViewerRegionInSearchQuery = function(query_string){
if (query_string){
query_string = query_string.substring(1);
var queries = query_string.split("&");
var indexViewerQuery = null;
for (var qI=0; qI -1){
indexViewerQuery = qI;
break;
}
}
if (indexViewerQuery != null){
queries.splice(indexViewerQuery, 1);
}
if (queries.length > 0){
query_string = "?" + queries.join("&") + "&";
} else {
query_string = "?";
}
} else {
query_string = "?";
}
return query_string;
};
/*
Make all the viewer bounds a float
Apply the fit bounds to arrange the image in the viewer
*/
var fitViewerToBounds = function(boundsStr){
var bounds = [];
var boundsArrayStr = boundsStr.split(",");
for (var iB=0; iB 4){
viewer.viewport.setRotation(bounds[4]);
}
viewer.viewport.fitBounds(new OpenSeadragon.Rect(bounds[0], bounds[1], bounds[2], bounds[3]), true);
};
/**
* Round each bound to the number of decimal places specified
* in the function
* @param bounds The bounds in an openSeadragon Rect() object
* @returns the bounds rounded still in the openSeadragon Rect()
*/
var roundBounds = function(bounds){
var numDecPlaces = 3;
bounds['x'] = roundToDec(bounds['x'], numDecPlaces);
bounds['y'] = roundToDec(bounds['y'], numDecPlaces);
bounds['width'] = roundToDec(bounds['width'], numDecPlaces);
bounds['height'] = roundToDec(bounds['height'], numDecPlaces);
return bounds;
};
/*
When a user clicks the back or forward button this is triggered
Looks for the "viewer" state. This would have been set by the
animation-finish in open seadragon
I don't think this is being used now and don't know if it will be
But it is here in case there is a case that I don't know about yet.
*/
window.addEventListener('popstate', function(pse){
if (pse.state){
if (pse.state.hasOwnProperty("region") > -1 && pse.state["region"] != null){
fitViewerToBounds(pse.state["region"]);
}
}
});
/*
If the viewer bounds are included in the JSON
on page load then use them to direct the viewer where to start
*/
viewer.addHandler("open", function(){
var bounds = "";
if (bounds){
fitViewerToBounds(bounds);
}
});
// Get the location of the image in the viewer and set it in the URL
function setViewportHistory() {
var path_info = location.pathname,
bounds = roundBounds(
viewer.viewport.getBounds()
),
query_string = removeViewerRegionInSearchQuery(
location.search
),
region = [
bounds.x,
bounds.y,
bounds.width,
bounds.height,
viewer.viewport.getRotation()
].join(',');
currentState = history.state;
let newState;
if(currentState != null){
newState = currentState;
}
else {
newState = {};
}
newState['region'] = region;
history.replaceState(
newState,
"ImageViewerRegion",
path_info + query_string + "r=" + region
);
}
viewer.addHandler("animation-finish", setViewportHistory);
viewer.addHandler("rotate", setViewportHistory);
/*
Build the buttons to be used for the confirm and cancel clipping
@param confirmCancel string saying "Confirm" or "Cancel"
@return a button for confirming or canceling the clipping
*/
var buildConfirmCancelClippingButtons = function(text){
var button = document.createElement("button");
button.appendChild(document.createTextNode(text));
return button;
};
// Changing the tool tip for the clip icon
OpenSeadragon.setString("Tooltips.SelectionToggle","Clip");
// Turned off keyboardShortcut to toggle mode
var viewer_selection = viewer.selection({
element: null, // html element to use for overlay
showSelectionControl: true, // show button to toggle selection mode
toggleButton: 'seadragon_clipper', // dom element to use as toggle button
confirmButton: buildConfirmCancelClippingButtons("Clip Image"),
cancelButton: buildConfirmCancelClippingButtons("Cancel"),
showConfirmDenyButtons: true,
styleConfirmDenyButtons: true,
returnPixelCoordinates: true,
keyboardShortcut: 'c', // key to toggle selection mode
rect: null, // initial selection as an OpenSeadragon.SelectionRect object
allowRotation: false, // turn selection rotation on or off as needed
startRotated: false, // alternative method for drawing the selection; useful for rotated crops
startRotatedHeight: 0.1, // only used if startRotated=true; value is relative to image height
restrictToImage: false, // true = do not allow any part of the selection to be outside the image
handleStyle: {
top: '50%',
left: '50%',
width: '6px',
height: '6px',
margin: '-4px 0 0 -4px',
background: '#0076AD',
border: '1px solid #0076AD'
},
cornersStyle: {
width: '6px',
height: '6px',
background: '#0076AD',
border: '1px solid #0076AD'
},
prefixUrl: null,
onSelection: function(rect) {
// Sending to a view
var clip_url = window.location.href;
var selectionBox = $('.selection-box', viewer.container);
var clipBox = {
width: selectionBox.width(),
height: selectionBox.height()
};
// Original code for query string iiif urls
var query_string = window.location.search;
clip_url = clip_url.replace(query_string, "");
query_string = removeViewerRegionInSearchQuery(query_string);
clip_url += query_string;
clip_url += "clip=" + rect.x +
"," + rect.y +
"," + rect.width +
"," + rect.height;
if (clipBox && clipBox['width']){
clip_url += "&ciw=" + clipBox['width'];
}
var viewerRotation = viewer.viewport.getRotation();
//Add the rotation to the clip_url
if (viewerRotation != null && viewerRotation != undefined){
clip_url += "&rot=" + viewerRotation;
}
// Once the feature gates are removed the clip_url will ALWAYS be
// ?clip=x,y,iiif_width,iii_height,img_width,rotation
window.open(clip_url);
},
});
/*
Don't let the buttons for the selection box exists outside the bottom of
the viewer. If the buttons start to leave the viewer the buttons
are moved to the top or the middle of the selection box.
Top by default, but if the selection box is too close to the top then
to the middle
This is triggered in three circumstances
1. The selection box is first being drawn
2. The selection box is being resized
3. The selection box is being dragged
*/
var positionSelectionButtons = function(){
var osdcB = document.getElementsByClassName("openseadragon-canvas")[0].getBoundingClientRect();
var sb = document.getElementsByClassName("selection-box")[0];
if (sb){
var sbDim = sb.getBoundingClientRect();
var sbBw = document.getElementsByClassName("clip-buttons-wrapper")[0];
var sbBwDim = sbBw.getBoundingClientRect();
// If the selection box buttons are leaving the bottom of the viewer
// Put a class in the selection box buttons wrapper
// This class will move the buttons either above or inside the selection box
if (Number(sbDim.bottom) + Number(sbBwDim.height) + 10 >= Number(osdcB.bottom)){
if (Number(sbDim.top - Number(sbBwDim.height) - 10) -1){
clipButtonHolder.classList.remove(classList[i]);
break;
}
}
clipButtonHolder.classList.add("button-rotate-" + viewer.viewport.getRotation());
}
viewer.addHandler("rotate", changeClippingButtonHolderClass);
$("#rotate-right").on('click', function(clickEvent) {
clickEvent.preventDefault();
viewer.viewport.setRotation((viewer.viewport.degrees + 90) % 360);
positionSelectionButtons();
});
viewer.addHandler('fullpage', function(viewer, details){
if( details.fullpage ){
setTimeout(function(){
$('#page-fulltext').attr('style', 'height:'+$(document).height()+'px !important;');
$('#viewer-image').attr('style', 'height:'+$(document).height()+'px !important;');
}, 15 );
}else{
$('#page-fulltext').attr('style', '');
$('#viewer-image').attr('style', '');
$('#full-screen').attr('style', '');
}
});
});
;;
};
viewerComponents['image'].onLoad = function(container){
(function($){
let $nextLink = $("#viewer-pagination-next");
let $previousLink = $("#viewer-pagination-previous");
if($nextLink.length){
let nextURL = new URL($nextLink.attr("href"));
nextURL.searchParams.set("st", "image");
$nextLink.attr("href", nextURL.href);
}
if($previousLink.length){
let previousURL = new URL($previousLink.attr("href"));
previousURL.searchParams.set("st", "image");
$previousLink.attr("href", previousURL.href);
}
})(jQuery);
};
viewerComponents['image'].validation = function(){
return true;
};
viewerComponents['pdf'].html= '
\n \n WEATHER INDICATIONS Increasing cloudiness today probably snow in the afternoon or nilit tomorrow snow Number 2817 An Era Aarking Advance in Washington Journalism There is no newspaper in Washington oi anywhere in fact south of New Yoik or Philadelphia that can match these magnificent printing machines Urto ttOTtlMWtt WASHTNGTOK FRIDAY FEBRUARY 14 1902 Wimtg Two New Presses for The Times Which Will Print gd000 READJHE NOON EDITION of THE TIMES Price One Cent An Embodiment of the Marvelous in American Invention Eight Page Papers an Hour or More Than i3 Papers Every Second- PfPBgwIgjCTriiJEPlB iwi Madllwffii at J ftffl cmicooih -A--v VraWV vny ts i j wafejiStiaf feKrATiM csmh j a OfcJM iv 3esa is itfifla tmssw rtM n u vTau nES53isjfca 5su isstp j s tsssa vfitaMii v eo smzv hi ten dajs after The Washington Times had WITUIX been purchased by its present owner orders had been placed for two of the finest and fastest newspaper presses in the world Their completion will maik a new era in the development of Washingtons newspapers and they will prove a revelation to those acquainted with former printing facilities in this city These two marvels of modern mechanical inventive ingenuity are technically known as the Ooss Latest Improved Quadruple Compound Straight- Money cannot be better invested anywhere than in making a clean wholesome uplifting newspaper for an intelligent and appreciative people line Printing Presses Their miraculous rapidity in mak ing white paper eloquent in turning out complete printed folded and counted newspapers at the late of S00 a minute each is almost bevond the power of human mind to coin prebend Thefc two presJes should be ready by the middle of April The acknowledgment of the order for them is inter esting and is printed herewith Chicago Nov CO 101 The Washington Times Washlncton D C Mr Frank A Munscy Dear Sir We beg to acknowledge receipt of contract Elton to Mr F V- Goss for two of our latest Impnned quadruple compound Etralghtline newspaper perfecting printing presses made up to jour Epeclat order In accordance with the measurements contained In said contract The machines are to be made up to includo all of our atett The price of these two presses and the stereo typing outfit 50000 is but an indication and an earnest of the financial policy of the present management in making a really great newspaper for the people of Washington proements and up to date In eery uny built on similar lines to those of our machines now In uic by the Herald of New York City We thank you tery kindly for the order and will be on time as tlpulated In the agreement Yours ery truly COSS PRINTING PRESS CO J J Walscr President and General Manager The world is making news at a frightfully rapid rate Those who choose to serve the public in recording this news and presenting it accurately justly and successfully must meet the conditions of splendid enterprise which make the American newspajyer of the day the wonder stud the mentor of the world They musl do this and mote N man or newspaper ever won by doing the sime thing asJiis neighbors just as well as his neighbors did it Jtutter work ever better work is a irv cornerstone of success 3 and progress 4 The great question is not alone the piodtictiou of it cer tain number of complete newspapeis but the almost in stantaneous production of an immense number of pers in order that readers in eerv section of the cityiniay tecche their paper almost simultaneously The period of the time betweenthe actual starting of he printing ma- r chinery and the completion of the entile edition must be i educed to a minimum The loss of a minute frejjiieiitly -makes all the difference between success and failure to be There are only two essentials in business suc cessin any business First Have adequate that is ample capital Second Sell your goods at a profit first in public service The latest news must be rushed in at the last moment before going to press Extras must be on the stieets in a minute or two following the reception 5 of startling news There is but one way to meet such i gencies that is by the introduction of the latest improved pi inting pi esses and machinery It is the purpose of the present management of The Times to give Washington City the best daily and Sunday newspaper it has ever had the best that money brains and modern machinery can produce The Washington Times proposes to be a very live and important factor in the citys daily life It is to be pro gressive aggressive fearless and fair It will woik der to shoulder with its citiens to make this city just what it by right should be thepiidc of its inhabitanfs an inspi ration and example among the people of the whole country THE VERY SOUL OF THE NATION So rapid are the improvements in the processes of printing that the modern machinery of today is aluicst an tiquated tomorrow Moreover as circulation increases ihere is it proportionate increase in the demand for newer lind better appliances The progressive and therefore the successful newspaper keeps up with the people who are the real pacemakers in every channel of business It was in iew of the steadily inct easing circulation of The Wash ington Times and in the belief that continually increasing excellence would find fruition in a still greater demand that the two magnificent proves now being made were ordered These machines are recognized as of the most advanced type of presses in the world today and are seemingly endowed with almost human intelligence The picture of the Goss press presented herewith gives but a faint idea of the in tricacy and lwauty the unerring accuracy and the brain beating rapidity of these marelous maefiines While two presses will be installed each is practically a double press If needs Le one side- of the press can be When these new presses of The Times are ready they Tvill be one of the sights of Washing ton an inspiring impresstbe educational sight And the public Jvill be welcomed worked on an edition entirely sepaiatc from that which is pioduced on the companion cylinders The reader will un derstand therefore that with the introduction of the two new fJoiP four distinct and separate new spaperi can be printed simultaneously Jn other woiTls by the use of separate plates a newspaper could be printed in four languages and sent out at one time to the sevetal classes of readers Hut for oidinaiy purposes duplicate plates aie used and the gteat machine turns out twin copies on both sides In using two presses the product will be four fold and the circulation department will be able to meet increasing demands for almost instantaneous supply With both presses in operation the daily issue of The Times will be printed at the rate of SIM a minute Yes eight hundred newspapers every minute Yet there is something more Ptoducing as these presses do a newspaper every one of the pages of which bears a clean impression without faintness or blur and so perfect typo graphically that it may be read at arms length with ease the achievement becomes greater than mere numbers show Quality will not be sacrificed to quantity in The Times of fice and the presses though required to have great speed among Washington newspapers in daily circulation THE TIMES must be fizst in mechanical equipment as well as intellectual -influence are also required to produce a newspaper which is as near erfection as the printers art and human care can make it Put eight hundred papers perfect typographically pro duced complete as each moment passes are not everything Were that all the o0000 investment in printing machinery and the many other thousands of dollars put into new types new apparatus and labor saving devices for the composing room aiid other mechanical departments would be only wasted Back of and above all this must be the There is a fascinating something in the work of perfectly adjusted machinery The genius of in vention approaches almost the miracle of creation determination and the ability to produce a great newspa per an honest newspaper a newspaper without prejudice and without pandering too big to be bought and too strong to be mean A NEWSPAPER OF THE PEOPLE OF WASHINGTON AND FOR THE PEOPLE OF WASH INGTON With newspapers as with men where there is financial need high ideals wither and die Money cannot do much good without ideas and ideals but the lack of money is the wide open door of temptation to eery man or news paper that struggles upward Already secure in the confi dence of the people of Washington with deep broad based plans and high ideals with every financial contingency provided for The Washington Times will labor beond the reach of any consideration except public good and business honesty to give the people u newspaper which will merit daj by day their ever growing confidence and support The installation of this efficient printing and stereotyping outfit is but the beginning the 1ery first step in an already fully planned progress Jbhicb ivill take The Times to a business home of its own in Washington erected by The Times for the use of The Times This announcement today of the new presses is but a detail of the programme Other details will become known htter and as soon as possible The Washington Times clever clean and fair will hare a business home of its swu built by it for its own uses in the heart of Wash ingtor City It is desired today simply without self-laudation to telLof our new presses and of how we mean to use them\n \n
\n\n\n\n\n';
viewerComponents['text'].onFirstLoad = function(container){
;;
jQuery(function($){
var fulltext_visible = false,
supplement_data_visible = false;
$("#page-fulltext-toggle").live("click", function(event){
event.preventDefault();
if( $(event.target).parents('.imageviewer_text, .control-section-text').hasClass('enabled') ){
if( !fulltext_visible ){
setTimeout(function(){
$("#page-fulltext").show();
}, 500);
fulltext_visible = true;
}else{
$("#page-fulltext").hide();
fulltext_visible = false;
}
}
});
$("#page-data-toggle").live("click", function(event){
event.preventDefault();
if( $(event.target).parents('.imageviewer_text, .control-section-text').hasClass('enabled') ){
if( !supplement_data_visible ){
setTimeout(function(){
$("#page-data").fadeIn("slow");
}, 500);
supplement_data_visible = true;
}else{
$("#page-data").fadeOut("slow");
supplement_data_visible = false;
}
}
});
var currentPage = 1,
showReferenceStrip = false;
var tileSources = [],
resource = [
{
"height": 6757,
"info": "https://tile.loc.gov/image-services/iiif/service:ndnp:dlc:batch_dlc_abe_ver01:data:sn87062245:100492969:1902021401:0529/info.json",
"mimetype": "image/jp2",
"size": 4322336,
"url": "https://tile.loc.gov/storage-services/service/ndnp/dlc/batch_dlc_abe_ver01/data/sn87062245/100492969/1902021401/0529.jp2",
"use": "",
"width": 5115
},
{
"mimetype": "application/pdf",
"url": "https://tile.loc.gov/storage-services/service/ndnp/dlc/batch_dlc_abe_ver01/data/sn87062245/100492969/1902021401/0529.pdf",
"use": ""
},
{
"mimetype": "text/xml",
"url": "https://tile.loc.gov/storage-services/service/ndnp/dlc/batch_dlc_abe_ver01/data/sn87062245/100492969/1902021401/0529.xml",
"use": ""
},
{
"height": 422,
"levels": 1,
"mimetype": "image/jpeg",
"url": "https://tile.loc.gov/image-services/iiif/service:ndnp:dlc:batch_dlc_abe_ver01:data:sn87062245:100492969:1902021401:0529/full/pct:6.25/0/default.jpg",
"width": 319
},
{
"height": 844,
"levels": 1,
"mimetype": "image/jpeg",
"url": "https://tile.loc.gov/image-services/iiif/service:ndnp:dlc:batch_dlc_abe_ver01:data:sn87062245:100492969:1902021401:0529/full/pct:12.5/0/default.jpg",
"width": 639
},
{
"height": 6757,
"info": "https://tile.loc.gov/image-services/iiif/service:ndnp:dlc:batch_dlc_abe_ver01:data:sn87062245:100492969:1902021401:0529/info.json",
"language": [
"english"
],
"mimetype": "application/json",
"reel_number": "100492969",
"section_label": null,
"size": 4322336,
"title": "Image 1 of The Washington times (Washington [D.C.]), February 14, 1902",
"width": 5115
},
{
"fulltext_service": "https://tile.loc.gov/text-services//word-coordinates-service?segment=/service/ndnp/dlc/batch_dlc_abe_ver01/data/sn87062245/100492969/1902021401/0529.xml&format=alto_xml&full_text=1",
"mimetype": "text/plain",
"use": "text"
}
],
source,
i;
for( i = 0; i = 0; i--){
levels.push(i);
}
// For maps jp2 stuff:
// x,y is center of tile adjusted for scale
// level is 0 based and reversed compared to seadragon
var x1 = this.tileSize / this.getLevelScale( level ) * x,
y1 = this.tileSize / this.getLevelScale( level ) * y,
delta = ( this.tileSize / this.getLevelScale( level ) ) / 2;
return tileService + '?' +
'&data=' + jp2_file +
'&x=' + ( x1 + delta ) +
'&y=' + ( y1 + delta ) +
'&res=' + levels[ level ] +
'&width=' + this.tileSize +
'&height=' + this.tileSize +
'&jpegLevel=' + 80;
}
});
}
}
}
var viewer = new OpenSeadragon.Viewer({
id: 'viewer-image',
fullscreen_element: $('#viewer-image-wrapper')[0],
toolbar: 'viewer-toolbar',
prefixUrl: '/static/js/lib/openseadragon-2.3.1/images/',
showNavigator: false,
showReferenceStrip: false,
referenceStripScroll: 'vertical',
autoHideControls: false,
nextButton: 'next',
previousButton: 'previous',
zoomInButton: 'zoom-in',
zoomOutButton: 'zoom-out',
rotateRightButton: 'rotate-right',
homeButton: 'home',
fullPageButton: 'full-screen',
tileSources: tileSources,
preserveViewport: true,
onPageChange: function( data ){ }
});
/**
* Round a number to the specified decimal places
* If num is not a number then just return without changes
* @param num The number to be rounded
* @param decPlaces The number of decimal places to round to
* @returns number rounded to the specified number of decimal places
*/
var roundToDec = function(num, decPlaces){
if (num && !isNaN(num)){
// If num is able to be a number convert it to that
// Round it to a fixed decimal places (which returns a string)
// Convert back to a number
return Number(Number(num).toFixed(decPlaces));
} else {
return num;
}
};
/*
Go through the URL search query and remove the r=...
You do this you move/zoom the view in the animation finish
And when you take a clipping
*/
var removeViewerRegionInSearchQuery = function(query_string){
if (query_string){
query_string = query_string.substring(1);
var queries = query_string.split("&");
var indexViewerQuery = null;
for (var qI=0; qI -1){
indexViewerQuery = qI;
break;
}
}
if (indexViewerQuery != null){
queries.splice(indexViewerQuery, 1);
}
if (queries.length > 0){
query_string = "?" + queries.join("&") + "&";
} else {
query_string = "?";
}
} else {
query_string = "?";
}
return query_string;
};
/*
Make all the viewer bounds a float
Apply the fit bounds to arrange the image in the viewer
*/
var fitViewerToBounds = function(boundsStr){
var bounds = [];
var boundsArrayStr = boundsStr.split(",");
for (var iB=0; iB 4){
viewer.viewport.setRotation(bounds[4]);
}
viewer.viewport.fitBounds(new OpenSeadragon.Rect(bounds[0], bounds[1], bounds[2], bounds[3]), true);
};
/**
* Round each bound to the number of decimal places specified
* in the function
* @param bounds The bounds in an openSeadragon Rect() object
* @returns the bounds rounded still in the openSeadragon Rect()
*/
var roundBounds = function(bounds){
var numDecPlaces = 3;
bounds['x'] = roundToDec(bounds['x'], numDecPlaces);
bounds['y'] = roundToDec(bounds['y'], numDecPlaces);
bounds['width'] = roundToDec(bounds['width'], numDecPlaces);
bounds['height'] = roundToDec(bounds['height'], numDecPlaces);
return bounds;
};
/*
When a user clicks the back or forward button this is triggered
Looks for the "viewer" state. This would have been set by the
animation-finish in open seadragon
I don't think this is being used now and don't know if it will be
But it is here in case there is a case that I don't know about yet.
*/
window.addEventListener('popstate', function(pse){
if (pse.state){
if (pse.state.hasOwnProperty("region") > -1 && pse.state["region"] != null){
fitViewerToBounds(pse.state["region"]);
}
}
});
/*
If the viewer bounds are included in the JSON
on page load then use them to direct the viewer where to start
*/
viewer.addHandler("open", function(){
var bounds = "";
if (bounds){
fitViewerToBounds(bounds);
}
});
// Get the location of the image in the viewer and set it in the URL
function setViewportHistory() {
var path_info = location.pathname,
bounds = roundBounds(
viewer.viewport.getBounds()
),
query_string = removeViewerRegionInSearchQuery(
location.search
),
region = [
bounds.x,
bounds.y,
bounds.width,
bounds.height,
viewer.viewport.getRotation()
].join(',');
currentState = history.state;
let newState;
if(currentState != null){
newState = currentState;
}
else {
newState = {};
}
newState['region'] = region;
history.replaceState(
newState,
"ImageViewerRegion",
path_info + query_string + "r=" + region
);
}
viewer.addHandler("animation-finish", setViewportHistory);
viewer.addHandler("rotate", setViewportHistory);
/*
Build the buttons to be used for the confirm and cancel clipping
@param confirmCancel string saying "Confirm" or "Cancel"
@return a button for confirming or canceling the clipping
*/
var buildConfirmCancelClippingButtons = function(text){
var button = document.createElement("button");
button.appendChild(document.createTextNode(text));
return button;
};
// Changing the tool tip for the clip icon
OpenSeadragon.setString("Tooltips.SelectionToggle","Clip");
// Turned off keyboardShortcut to toggle mode
var viewer_selection = viewer.selection({
element: null, // html element to use for overlay
showSelectionControl: true, // show button to toggle selection mode
toggleButton: 'seadragon_clipper', // dom element to use as toggle button
confirmButton: buildConfirmCancelClippingButtons("Clip Image"),
cancelButton: buildConfirmCancelClippingButtons("Cancel"),
showConfirmDenyButtons: true,
styleConfirmDenyButtons: true,
returnPixelCoordinates: true,
keyboardShortcut: 'c', // key to toggle selection mode
rect: null, // initial selection as an OpenSeadragon.SelectionRect object
allowRotation: false, // turn selection rotation on or off as needed
startRotated: false, // alternative method for drawing the selection; useful for rotated crops
startRotatedHeight: 0.1, // only used if startRotated=true; value is relative to image height
restrictToImage: false, // true = do not allow any part of the selection to be outside the image
handleStyle: {
top: '50%',
left: '50%',
width: '6px',
height: '6px',
margin: '-4px 0 0 -4px',
background: '#0076AD',
border: '1px solid #0076AD'
},
cornersStyle: {
width: '6px',
height: '6px',
background: '#0076AD',
border: '1px solid #0076AD'
},
prefixUrl: null,
onSelection: function(rect) {
// Sending to a view
var clip_url = window.location.href;
var selectionBox = $('.selection-box', viewer.container);
var clipBox = {
width: selectionBox.width(),
height: selectionBox.height()
};
// Original code for query string iiif urls
var query_string = window.location.search;
clip_url = clip_url.replace(query_string, "");
query_string = removeViewerRegionInSearchQuery(query_string);
clip_url += query_string;
clip_url += "clip=" + rect.x +
"," + rect.y +
"," + rect.width +
"," + rect.height;
if (clipBox && clipBox['width']){
clip_url += "&ciw=" + clipBox['width'];
}
var viewerRotation = viewer.viewport.getRotation();
//Add the rotation to the clip_url
if (viewerRotation != null && viewerRotation != undefined){
clip_url += "&rot=" + viewerRotation;
}
// Once the feature gates are removed the clip_url will ALWAYS be
// ?clip=x,y,iiif_width,iii_height,img_width,rotation
window.open(clip_url);
},
});
/*
Don't let the buttons for the selection box exists outside the bottom of
the viewer. If the buttons start to leave the viewer the buttons
are moved to the top or the middle of the selection box.
Top by default, but if the selection box is too close to the top then
to the middle
This is triggered in three circumstances
1. The selection box is first being drawn
2. The selection box is being resized
3. The selection box is being dragged
*/
var positionSelectionButtons = function(){
var osdcB = document.getElementsByClassName("openseadragon-canvas")[0].getBoundingClientRect();
var sb = document.getElementsByClassName("selection-box")[0];
if (sb){
var sbDim = sb.getBoundingClientRect();
var sbBw = document.getElementsByClassName("clip-buttons-wrapper")[0];
var sbBwDim = sbBw.getBoundingClientRect();
// If the selection box buttons are leaving the bottom of the viewer
// Put a class in the selection box buttons wrapper
// This class will move the buttons either above or inside the selection box
if (Number(sbDim.bottom) + Number(sbBwDim.height) + 10 >= Number(osdcB.bottom)){
if (Number(sbDim.top - Number(sbBwDim.height) - 10) -1){
clipButtonHolder.classList.remove(classList[i]);
break;
}
}
clipButtonHolder.classList.add("button-rotate-" + viewer.viewport.getRotation());
}
viewer.addHandler("rotate", changeClippingButtonHolderClass);
$("#rotate-right").on('click', function(clickEvent) {
clickEvent.preventDefault();
viewer.viewport.setRotation((viewer.viewport.degrees + 90) % 360);
positionSelectionButtons();
});
viewer.addHandler('fullpage', function(viewer, details){
if( details.fullpage ){
setTimeout(function(){
$('#page-fulltext').attr('style', 'height:'+$(document).height()+'px !important;');
$('#viewer-image').attr('style', 'height:'+$(document).height()+'px !important;');
}, 15 );
}else{
$('#page-fulltext').attr('style', '');
$('#viewer-image').attr('style', '');
$('#full-screen').attr('style', '');
}
});
});
;;
const fulltext = `WEATHER INDICATIONS\nIncreasing cloudiness today probably snow\nin the afternoon or nilit tomorrow snow\nNumber 2817\nAn Era Aarking Advance in\nWashington Journalism\nThere is\nno newspaper\nin Washington\noi anywhere\nin fact\nsouth of\nNew Yoik or\nPhiladelphia\nthat can match\nthese\nmagnificent\nprinting\nmachines\nUrto\nttOTtlMWtt\nWASHTNGTOK FRIDAY FEBRUARY 14 1902\nWimtg\nTwo New Presses for The Times Which Will Print gd000\nREADJHE\nNOON EDITION\nof THE TIMES\nPrice One Cent\nAn Embodiment of the Marvelous\nin American Invention\nEight Page Papers an Hour or More Than i3 Papers Every Second-\nPfPBgwIgjCTriiJEPlB iwi Madllwffii at J ftffl cmicooih -A--v VraWV vny ts i\nj wafejiStiaf feKrATiM csmh j a OfcJM iv 3esa is itfifla tmssw rtM n u vTau\nnES53isjfca 5su isstp j s tsssa vfitaMii v eo smzv\nhi\nten dajs after The Washington Times had\nWITUIX\nbeen purchased by its present owner orders had\nbeen placed for two of the finest and fastest newspaper\npresses in the world Their completion will maik a new era\nin the development of Washingtons newspapers and they\nwill prove a revelation to those acquainted with former\nprinting facilities in this city These two marvels of modern\nmechanical inventive ingenuity are technically known as\nthe Ooss Latest Improved Quadruple Compound Straight-\nMoney cannot be better invested anywhere than\nin making a clean wholesome uplifting newspaper\nfor an intelligent and appreciative people\nline Printing Presses Their miraculous rapidity in mak\ning white paper eloquent in turning out complete printed\nfolded and counted newspapers at the late of S00 a minute\neach is almost bevond the power of human mind to coin\nprebend\nThefc two presJes should be ready by the middle of\nApril The acknowledgment of the order for them is inter\nesting and is printed herewith\nChicago Nov CO 101\nThe Washington Times Washlncton D C\nMr Frank A Munscy\nDear Sir We beg to acknowledge receipt of contract Elton to\nMr F V- Goss for two of our latest Impnned quadruple compound\nEtralghtline newspaper perfecting printing presses made up to jour\nEpeclat order In accordance with the measurements contained In said\ncontract\nThe machines are to be made up to includo all of our atett\nThe price of these two presses and the stereo\ntyping outfit 50000 is but an indication and\nan earnest of the financial policy of the present\nmanagement in making a really great newspaper\nfor the people of Washington\nproements and up to date In eery uny built on similar lines to those\nof our machines now In uic by the Herald of New York City\nWe thank you tery kindly for the order and will be on time as\ntlpulated In the agreement Yours ery truly\nCOSS PRINTING PRESS CO\nJ J Walscr President and General Manager\nThe world is making news at a frightfully rapid rate\nThose who choose to serve the public in recording this\nnews and presenting it accurately justly and successfully\nmust meet the conditions of splendid enterprise which\nmake the American newspajyer of the day the wonder stud\nthe mentor of the world They musl do this and mote N\nman or newspaper ever won by doing the sime thing asJiis\nneighbors just as well as his neighbors did it Jtutter\nwork ever better work is a irv cornerstone of success\n3\nand progress 4\nThe great question is not alone the piodtictiou of it cer\ntain number of complete newspapeis but the almost in\nstantaneous production of an immense number of\npers in order that readers in eerv section of the cityiniay\ntecche their paper almost simultaneously The period of\nthe time betweenthe actual starting of he printing ma- r\nchinery and the completion of the entile edition must be\ni educed to a minimum The loss of a minute frejjiieiitly -makes\nall the difference between success and failure to be\nThere are only two essentials in business suc\ncessin any business First Have adequate that\nis ample capital Second Sell your goods at a\nprofit\nfirst in public service The latest news must be rushed in\nat the last moment before going to press Extras must be\non the stieets in a minute or two following the reception 5\nof startling news There is but one way to meet such\ni\ngencies that is by the introduction of the latest improved\npi inting pi esses and machinery\nIt is the purpose of the present management of The\nTimes to give Washington City the best daily and Sunday\nnewspaper it has ever had the best that money brains\nand modern machinery can produce\nThe Washington Times proposes to be a very live and\nimportant factor in the citys daily life It is to be pro\ngressive aggressive fearless and fair It will woik\nder to shoulder with its citiens to make this city just what\nit by right should be thepiidc of its inhabitanfs an inspi\nration and example among the people of the whole country\nTHE VERY SOUL OF THE NATION\nSo rapid are the improvements in the processes of\nprinting that the modern machinery of today is aluicst an\ntiquated tomorrow Moreover as circulation increases\nihere is it proportionate increase in the demand for newer\nlind better appliances The progressive and therefore the\nsuccessful newspaper keeps up with the people who are\nthe real pacemakers in every channel of business It was\nin iew of the steadily inct easing circulation of The Wash\nington Times and in the belief that continually increasing\nexcellence would find fruition in a still greater demand that\nthe two magnificent proves now being made were ordered\nThese machines are recognized as of the most advanced type\nof presses in the world today and are seemingly endowed\nwith almost human intelligence The picture of the Goss\npress presented herewith gives but a faint idea of the in\ntricacy and lwauty the unerring accuracy and the brain\nbeating rapidity of these marelous maefiines\nWhile two presses will be installed each is practically\na double press If needs Le one side- of the press can be\nWhen these new presses of The Times are\nready they Tvill be one of the sights of Washing\nton an inspiring impresstbe educational sight\nAnd the public Jvill be welcomed\nworked on an edition entirely sepaiatc from that which is\npioduced on the companion cylinders The reader will un\nderstand therefore that with the introduction of the two\nnew fJoiP four distinct and separate new spaperi\ncan be printed simultaneously Jn other woiTls by the use\nof separate plates a newspaper could be printed in four\nlanguages and sent out at one time to the sevetal classes\nof readers Hut for oidinaiy purposes duplicate plates\naie used and the gteat machine turns out twin copies on\nboth sides In using two presses the product will be four\nfold and the circulation department will be able to meet\nincreasing demands for almost instantaneous supply With\nboth presses in operation the daily issue of The Times will\nbe printed at the rate of SIM a minute\nYes eight hundred newspapers every minute Yet\nthere is something more Ptoducing as these presses do a\nnewspaper every one of the pages of which bears a clean\nimpression without faintness or blur and so perfect typo\ngraphically that it may be read at arms length with ease\nthe achievement becomes greater than mere numbers show\nQuality will not be sacrificed to quantity in The Times of\nfice and the presses though required to have great speed\namong\nWashington\nnewspapers\nin daily\ncirculation\nTHE TIMES\nmust be\nfizst in\nmechanical\nequipment\nas well as\nintellectual -influence\nare also required to produce a newspaper which is as near\nerfection as the printers art and human care can make it\nPut eight hundred papers perfect typographically pro\nduced complete as each moment passes are not everything\nWere that all the o0000 investment in printing machinery\nand the many other thousands of dollars put into new\ntypes new apparatus and labor saving devices for the\ncomposing room aiid other mechanical departments would\nbe only wasted Back of and above all this must be the\nThere is a fascinating something in the work of\nperfectly adjusted machinery The genius of in\nvention approaches almost the miracle of creation\ndetermination and the ability to produce a great newspa\nper an honest newspaper a newspaper without prejudice\nand without pandering too big to be bought and too\nstrong to be mean A NEWSPAPER OF THE PEOPLE\nOF WASHINGTON AND FOR THE PEOPLE OF WASH\nINGTON\nWith newspapers as with men where there is financial\nneed high ideals wither and die Money cannot do much\ngood without ideas and ideals but the lack of money\nis the wide open door of temptation to eery man or news\npaper that struggles upward Already secure in the confi\ndence of the people of Washington with deep broad based\nplans and high ideals with every financial contingency\nprovided for The Washington Times will labor beond the\nreach of any consideration except public good and business\nhonesty to give the people u newspaper which will merit\ndaj by day their ever growing confidence and support\nThe installation of this efficient printing and\nstereotyping outfit is but the beginning the 1ery\nfirst step in an already fully planned progress\nJbhicb ivill take The Times to a business home\nof its own in Washington erected by The Times\nfor the use of The Times\nThis announcement today of the new presses is but a\ndetail of the programme Other details will become known\nhtter and as soon as possible The Washington Times\nclever clean and fair will hare a business home of its\nswu built by it for its own uses in the heart of Wash\ningtor City It is desired today simply without self-laudation\nto telLof our new presses and of how we mean to use\nthem`;
if(fulltext !=null && fulltext.trim() != '') {
document.getElementById("fulltext-box").innerHTML = `WEATHER INDICATIONS Increasing cloudiness today probably snow in the afternoon or nilit tomorrow snow Number 2817 An Era Aarking Advance in Washington Journalism There is no newspaper in Washington oi anywhere in fact south of New Yoik or Philadelphia that can match these magnificent printing machines Urto ttOTtlMWtt WASHTNGTOK FRIDAY FEBRUARY 14 1902 Wimtg Two New Presses for The Times Which Will Print gd000 READJHE NOON EDITION of THE TIMES Price One Cent An Embodiment of the Marvelous in American Invention Eight Page Papers an Hour or More Than i3 Papers Every Second- PfPBgwIgjCTriiJEPlB iwi Madllwffii at J ftffl cmicooih -A--v VraWV vny ts i j wafejiStiaf feKrATiM csmh j a OfcJM iv 3esa is itfifla tmssw rtM n u vTau nES53isjfca 5su isstp j s tsssa vfitaMii v eo smzv hi ten dajs after The Washington Times had WITUIX been purchased by its present owner orders had been placed for two of the finest and fastest newspaper presses in the world Their completion will maik a new era in the development of Washingtons newspapers and they will prove a revelation to those acquainted with former printing facilities in this city These two marvels of modern mechanical inventive ingenuity are technically known as the Ooss Latest Improved Quadruple Compound Straight- Money cannot be better invested anywhere than in making a clean wholesome uplifting newspaper for an intelligent and appreciative people line Printing Presses Their miraculous rapidity in mak ing white paper eloquent in turning out complete printed folded and counted newspapers at the late of S00 a minute each is almost bevond the power of human mind to coin prebend Thefc two presJes should be ready by the middle of April The acknowledgment of the order for them is inter esting and is printed herewith Chicago Nov CO 101 The Washington Times Washlncton D C Mr Frank A Munscy Dear Sir We beg to acknowledge receipt of contract Elton to Mr F V- Goss for two of our latest Impnned quadruple compound Etralghtline newspaper perfecting printing presses made up to jour Epeclat order In accordance with the measurements contained In said contract The machines are to be made up to includo all of our atett The price of these two presses and the stereo typing outfit 50000 is but an indication and an earnest of the financial policy of the present management in making a really great newspaper for the people of Washington proements and up to date In eery uny built on similar lines to those of our machines now In uic by the Herald of New York City We thank you tery kindly for the order and will be on time as tlpulated In the agreement Yours ery truly COSS PRINTING PRESS CO J J Walscr President and General Manager The world is making news at a frightfully rapid rate Those who choose to serve the public in recording this news and presenting it accurately justly and successfully must meet the conditions of splendid enterprise which make the American newspajyer of the day the wonder stud the mentor of the world They musl do this and mote N man or newspaper ever won by doing the sime thing asJiis neighbors just as well as his neighbors did it Jtutter work ever better work is a irv cornerstone of success 3 and progress 4 The great question is not alone the piodtictiou of it cer tain number of complete newspapeis but the almost in stantaneous production of an immense number of pers in order that readers in eerv section of the cityiniay tecche their paper almost simultaneously The period of the time betweenthe actual starting of he printing ma- r chinery and the completion of the entile edition must be i educed to a minimum The loss of a minute frejjiieiitly -makes all the difference between success and failure to be There are only two essentials in business suc cessin any business First Have adequate that is ample capital Second Sell your goods at a profit first in public service The latest news must be rushed in at the last moment before going to press Extras must be on the stieets in a minute or two following the reception 5 of startling news There is but one way to meet such i gencies that is by the introduction of the latest improved pi inting pi esses and machinery It is the purpose of the present management of The Times to give Washington City the best daily and Sunday newspaper it has ever had the best that money brains and modern machinery can produce The Washington Times proposes to be a very live and important factor in the citys daily life It is to be pro gressive aggressive fearless and fair It will woik der to shoulder with its citiens to make this city just what it by right should be thepiidc of its inhabitanfs an inspi ration and example among the people of the whole country THE VERY SOUL OF THE NATION So rapid are the improvements in the processes of printing that the modern machinery of today is aluicst an tiquated tomorrow Moreover as circulation increases ihere is it proportionate increase in the demand for newer lind better appliances The progressive and therefore the successful newspaper keeps up with the people who are the real pacemakers in every channel of business It was in iew of the steadily inct easing circulation of The Wash ington Times and in the belief that continually increasing excellence would find fruition in a still greater demand that the two magnificent proves now being made were ordered These machines are recognized as of the most advanced type of presses in the world today and are seemingly endowed with almost human intelligence The picture of the Goss press presented herewith gives but a faint idea of the in tricacy and lwauty the unerring accuracy and the brain beating rapidity of these marelous maefiines While two presses will be installed each is practically a double press If needs Le one side- of the press can be When these new presses of The Times are ready they Tvill be one of the sights of Washing ton an inspiring impresstbe educational sight And the public Jvill be welcomed worked on an edition entirely sepaiatc from that which is pioduced on the companion cylinders The reader will un derstand therefore that with the introduction of the two new fJoiP four distinct and separate new spaperi can be printed simultaneously Jn other woiTls by the use of separate plates a newspaper could be printed in four languages and sent out at one time to the sevetal classes of readers Hut for oidinaiy purposes duplicate plates aie used and the gteat machine turns out twin copies on both sides In using two presses the product will be four fold and the circulation department will be able to meet increasing demands for almost instantaneous supply With both presses in operation the daily issue of The Times will be printed at the rate of SIM a minute Yes eight hundred newspapers every minute Yet there is something more Ptoducing as these presses do a newspaper every one of the pages of which bears a clean impression without faintness or blur and so perfect typo graphically that it may be read at arms length with ease the achievement becomes greater than mere numbers show Quality will not be sacrificed to quantity in The Times of fice and the presses though required to have great speed among Washington newspapers in daily circulation THE TIMES must be fizst in mechanical equipment as well as intellectual -influence are also required to produce a newspaper which is as near erfection as the printers art and human care can make it Put eight hundred papers perfect typographically pro duced complete as each moment passes are not everything Were that all the o0000 investment in printing machinery and the many other thousands of dollars put into new types new apparatus and labor saving devices for the composing room aiid other mechanical departments would be only wasted Back of and above all this must be the There is a fascinating something in the work of perfectly adjusted machinery The genius of in vention approaches almost the miracle of creation determination and the ability to produce a great newspa per an honest newspaper a newspaper without prejudice and without pandering too big to be bought and too strong to be mean A NEWSPAPER OF THE PEOPLE OF WASHINGTON AND FOR THE PEOPLE OF WASH INGTON With newspapers as with men where there is financial need high ideals wither and die Money cannot do much good without ideas and ideals but the lack of money is the wide open door of temptation to eery man or news paper that struggles upward Already secure in the confi dence of the people of Washington with deep broad based plans and high ideals with every financial contingency provided for The Washington Times will labor beond the reach of any consideration except public good and business honesty to give the people u newspaper which will merit daj by day their ever growing confidence and support The installation of this efficient printing and stereotyping outfit is but the beginning the 1ery first step in an already fully planned progress Jbhicb ivill take The Times to a business home of its own in Washington erected by The Times for the use of The Times This announcement today of the new presses is but a detail of the programme Other details will become known htter and as soon as possible The Washington Times clever clean and fair will hare a business home of its swu built by it for its own uses in the heart of Wash ingtor City It is desired today simply without self-laudation to telLof our new presses and of how we mean to use them`
} else {
(function($){
$.getJSON("https://tile.loc.gov/text-services//word-coordinates-service?segment=/service/ndnp/dlc/batch_dlc_abe_ver01/data/sn87062245/100492969/1902021401/0529.xml&format=alto_xml&full_text=1", function(data){
document.getElementById("fulltext-box").innerText = data["/service/ndnp/dlc/batch_dlc_abe_ver01/data/sn87062245/100492969/1902021401/0529.xml"]["full_text"].replace(/&/gi, "&");
});
})(jQuery);
};
}
viewerComponents['text'].onLoad = function(container){
(function($){
let $nextLink = $("#viewer-pagination-next");
let $previousLink = $("#viewer-pagination-previous");
if($nextLink.length){
let nextURL = new URL($nextLink.attr("href"));
nextURL.searchParams.set("st", "text");
$nextLink.attr("href", nextURL.href);
}
if($previousLink.length){
let previousURL = new URL($previousLink.attr("href"));
previousURL.searchParams.set("st", "text");
$previousLink.attr("href", previousURL.href);
}
})(jQuery);
};
viewerComponents['text'].validation = function(){
return true;
};
const deactivateOldComponent = function(container, controls){
let componentContainer = container.children("#" + viewerComponents[activeComponent].id);
// This occurs when the active component is not one we explicitly support--i.e., the default
// This should only happen when a supported component is loaded after the page is loaded
// with the default component, so we don't need to worry about other children.
// However, to be safe, we only grab the first child, since all other components are
// appended to the container.
if(componentContainer.length === 0){
componentContainer = container.children().slice(0, 1);
}
if(viewerComponents[activeComponent].detachable === true){
storedComponents[activeComponent] = componentContainer.detach();
} else {
storedComponents[activeComponent] = componentContainer;
storedComponents[activeComponent].hide();
storedComponents[activeComponent].attr('aria-hidden', 'true');
}
controls.html('');
//Use of .call(window...) below is so `this` inside the function is window instead of the function itself
viewerComponents[activeComponent].onUnload.call(window, container);
if(viewerComponents[activeComponent].buttonId != null){
deselectTab(viewerComponents[activeComponent].buttonId);
}
}
const activateNewComponent = function(container, component, controls){
//Use of .call(window...) below is so `this` inside the function is window instead of the function itself
if(component in storedComponents){
if(viewerComponents[component].detachable === true){
container.append(storedComponents[component]);
} else {
storedComponents[component].show()
storedComponents[component].attr('aria-hidden', 'false');
}
} else {
container.append(viewerComponents[component]['html']);
viewerComponents[component].onFirstLoad.call(window, container);
}
viewerComponents[component].onLoad.call(window, container);
controls.html(viewerComponents[component]['controls']);
if(viewerComponents[component].buttonId != null){
selectTab(viewerComponents[component].buttonId);
}
activeComponent = component;
}
const activateComponent = function(component){
if(!(component in viewerComponents)){
component = "default";
}
if(activeComponent == null){
activeComponent = 'default';
}
if(activeComponent === component){
return;
}
let container = $("#" + viewerContainer);
let controls = $("#" + controlsContainer);
deactivateOldComponent(container, controls);
activateNewComponent(container, component, controls);
};
const navigateTo = function(component){
let searchParams = new URLSearchParams(window.location.search);
searchParams.set('st', component);
let newURL = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' + searchParams.toString();
window.history.pushState({"st": component}, '', newURL);
activateComponent(component);
};
jQuery(function($){
let searchParams = new URLSearchParams(window.location.search);
let component = searchParams.get('st');
if(component == null || component === "single"){
activateComponent("image");
}
else if(component in viewerComponents){
if(viewerComponents[component].validation()){
activateComponent(component);
}else{
activateComponent("image");
}
}
else{
activeComponent = 'default';
}
window.history.replaceState({"st" : component}, '', window.location);
});
window.onpopstate = function(event){
let component = event.state['st'];
if(component != null){
activateComponent(component);
}
};
Image provided by: Library of Congress, Washington, DC
About this Newspaper
Title
The Washington times (Washington [D.C.]), February 14, 1902
The Library of Congress believes that the newspapers in Chronicling America are in the public domain or have no known copyright restrictions. Newspapers published in the United States more than 95 years ago are in the public domain in their entirety. Any newspapers in Chronicling America that were published less than 95 years ago are also believed to be in the public domain, but may contain some copyrighted third party materials. Researchers using newspapers published less than 95 years ago should be alert for modern content (for example, registered and renewed for copyright and published with notice) that may be copyrighted. Responsibility for making an independent legal assessment of an item and securing any necessary permissions ultimately rests with persons desiring to use the item.
The NEH awardee responsible for producing each digital object is presented in the Chronicling America page display, below the page image – e.g. Image produced by the Library of Congress. For more information on current NDNP awardees, see https://www.loc.gov/ndnp/listawardees.html.