diff options
author | Andrew Dolgov <[email protected]> | 2017-06-09 15:13:51 +0300 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2017-06-09 15:13:51 +0300 |
commit | bbd8f03dfb41595e9b6513a656ca14b68695632f (patch) | |
tree | d88191b9aece7b05d0bd21a91b2193f53b3e4458 | |
parent | 4fe174cd142731f3131a05b1753cf3a0fcae0340 (diff) |
update epub.js
-rw-r--r-- | lib/epub.js | 417 |
1 files changed, 266 insertions, 151 deletions
diff --git a/lib/epub.js b/lib/epub.js index c00249d..a45e06d 100644 --- a/lib/epub.js +++ b/lib/epub.js @@ -3,13 +3,13 @@ * @copyright Copyright (c) 2016 Yehuda Katz, Tom Dale, Stefan Penner and contributors * @license Licensed under MIT license * See https://raw.githubusercontent.com/tildeio/rsvp.js/master/LICENSE - * @version 3.3.3 + * @version 3.5.0 */ (function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (factory((global.RSVP = global.RSVP || {}))); + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.RSVP = global.RSVP || {}))); }(this, (function (exports) { 'use strict'; function indexOf(callbacks, callback) { @@ -283,7 +283,7 @@ function scheduleFlush() { queue.length = 0; }, 50); } -function instrument(eventName, promise, child) { +function instrument$1(eventName, promise, child) { if (1 === queue.push({ name: eventName, payload: { @@ -366,18 +366,18 @@ function getThen(promise) { } } -function tryThen(then, value, fulfillmentHandler, rejectionHandler) { +function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) { try { - then.call(value, fulfillmentHandler, rejectionHandler); + then$$1.call(value, fulfillmentHandler, rejectionHandler); } catch (e) { return e; } } -function handleForeignThenable(promise, thenable, then) { +function handleForeignThenable(promise, thenable, then$$1) { config.async(function (promise) { var sealed = false; - var error = tryThen(then, thenable, function (value) { + var error = tryThen(then$$1, thenable, function (value) { if (sealed) { return; } @@ -422,16 +422,17 @@ function handleOwnThenable(promise, thenable) { } } -function handleMaybeThenable(promise, maybeThenable, then$$) { - if (maybeThenable.constructor === promise.constructor && then$$ === then && promise.constructor.resolve === resolve$1) { +function handleMaybeThenable(promise, maybeThenable, then$$1) { + if (maybeThenable.constructor === promise.constructor && then$$1 === then && promise.constructor.resolve === resolve$1) { handleOwnThenable(promise, maybeThenable); } else { - if (then$$ === GET_THEN_ERROR) { + if (then$$1 === GET_THEN_ERROR) { reject(promise, GET_THEN_ERROR.error); - } else if (then$$ === undefined) { + GET_THEN_ERROR.error = null; + } else if (then$$1 === undefined) { fulfill(promise, maybeThenable); - } else if (isFunction(then$$)) { - handleForeignThenable(promise, maybeThenable, then$$); + } else if (isFunction(then$$1)) { + handleForeignThenable(promise, maybeThenable, then$$1); } else { fulfill(promise, maybeThenable); } @@ -466,7 +467,7 @@ function fulfill(promise, value) { if (promise._subscribers.length === 0) { if (config.instrument) { - instrument('fulfilled', promise); + instrument$1('fulfilled', promise); } } else { config.async(publish, promise); @@ -502,7 +503,7 @@ function publish(promise) { var settled = promise._state; if (config.instrument) { - instrument(settled === FULFILLED ? 'fulfilled' : 'rejected', promise); + instrument$1(settled === FULFILLED ? 'fulfilled' : 'rejected', promise); } if (subscribers.length === 0) { @@ -555,10 +556,10 @@ function invokeCallback(settled, promise, callback, detail) { if (value === TRY_CATCH_ERROR) { failed = true; error = value.error; - value = null; + value.error = null; // release } else { - succeeded = true; - } + succeeded = true; + } if (promise === value) { reject(promise, withOwnPromise()); @@ -610,7 +611,7 @@ function then(onFulfillment, onRejection, label) { var state = parent._state; if (state === FULFILLED && !onFulfillment || state === REJECTED && !onRejection) { - config.instrument && instrument('chained', parent, parent); + config.instrument && instrument$1('chained', parent, parent); return parent; } @@ -619,7 +620,7 @@ function then(onFulfillment, onRejection, label) { var child = new parent.constructor(noop, label); var result = parent._result; - config.instrument && instrument('chained', parent, child); + config.instrument && instrument$1('chained', parent, child); if (state) { (function () { @@ -699,28 +700,28 @@ Enumerator.prototype._enumerate = function () { Enumerator.prototype._settleMaybeThenable = function (entry, i) { var c = this._instanceConstructor; - var resolve = c.resolve; + var resolve$$1 = c.resolve; - if (resolve === resolve$1) { - var then$$ = getThen(entry); + if (resolve$$1 === resolve$1) { + var then$$1 = getThen(entry); - if (then$$ === then && entry._state !== PENDING) { + if (then$$1 === then && entry._state !== PENDING) { entry._onError = null; this._settledAt(entry._state, i, entry._result); - } else if (typeof then$$ !== 'function') { + } else if (typeof then$$1 !== 'function') { this._remaining--; this._result[i] = this._makeResult(FULFILLED, i, entry); - } else if (c === Promise) { + } else if (c === Promise$1) { var promise = new c(noop); - handleMaybeThenable(promise, entry, then$$); + handleMaybeThenable(promise, entry, then$$1); this._willSettleAt(promise, i); } else { - this._willSettleAt(new c(function (resolve) { - return resolve(entry); + this._willSettleAt(new c(function (resolve$$1) { + return resolve$$1(entry); }), i); } } else { - this._willSettleAt(resolve(entry), i); + this._willSettleAt(resolve$$1(entry), i); } }; @@ -812,7 +813,7 @@ Enumerator.prototype._willSettleAt = function (promise, i) { fulfilled, or rejected if any of them become rejected. @static */ -function all(entries, label) { +function all$1(entries, label) { return new Enumerator(this, entries, true, /* abort on reject */label).promise; } @@ -882,7 +883,7 @@ function all(entries, label) { @return {Promise} a promise which settles in the same way as the first passed promise to settle. */ -function race(entries, label) { +function race$1(entries, label) { /*jshint validthis:true */ var Constructor = this; @@ -1062,29 +1063,29 @@ function needsNew() { Useful for tooling. @constructor */ -function Promise(resolver, label) { +function Promise$1(resolver, label) { this._id = counter++; this._label = label; this._state = undefined; this._result = undefined; this._subscribers = []; - config.instrument && instrument('created', this); + config.instrument && instrument$1('created', this); if (noop !== resolver) { typeof resolver !== 'function' && needsResolver(); - this instanceof Promise ? initializePromise(this, resolver) : needsNew(); + this instanceof Promise$1 ? initializePromise(this, resolver) : needsNew(); } } -Promise.cast = resolve$1; // deprecated -Promise.all = all; -Promise.race = race; -Promise.resolve = resolve$1; -Promise.reject = reject$1; +Promise$1.cast = resolve$1; // deprecated +Promise$1.all = all$1; +Promise$1.race = race$1; +Promise$1.resolve = resolve$1; +Promise$1.reject = reject$1; -Promise.prototype = { - constructor: Promise, +Promise$1.prototype = { + constructor: Promise$1, _guidKey: guidKey, @@ -1342,7 +1343,7 @@ Promise.prototype = { try { return findAuthor(); // succeed or fail } catch(error) { - return findOtherAuther(); + return findOtherAuthor(); } finally { // always runs // doesn't affect the return value @@ -1353,7 +1354,7 @@ Promise.prototype = { ```js findAuthor().catch(function(reason){ - return findOtherAuther(); + return findOtherAuthor(); }).finally(function(){ // author was either found, or not }); @@ -1570,7 +1571,7 @@ function wrapThenable(_then, promise) { `RSVP.Promise` @static */ -function denodeify(nodeFunc, options) { +function denodeify$1(nodeFunc, options) { var fn = function fn() { var self = this; var l = arguments.length; @@ -1584,7 +1585,7 @@ function denodeify(nodeFunc, options) { // TODO: clean this up promiseInput = needsPromiseInput(arg); if (promiseInput === GET_THEN_ERROR$1) { - var p = new Promise(noop); + var p = new Promise$1(noop); reject(p, GET_THEN_ERROR$1.value); return p; } else if (promiseInput && promiseInput !== true) { @@ -1594,7 +1595,7 @@ function denodeify(nodeFunc, options) { args[i] = arg; } - var promise = new Promise(noop); + var promise = new Promise$1(noop); args[l] = function (err, val) { if (err) reject(promise, err);else if (options === undefined) resolve(promise, val);else if (options === true) resolve(promise, arrayResult(arguments));else if (isArray(options)) resolve(promise, makeObject(arguments, options));else resolve(promise, val); @@ -1621,7 +1622,7 @@ function handleValueInput(promise, args, nodeFunc, self) { } function handlePromiseInput(promise, args, nodeFunc, self) { - return Promise.all(args).then(function (args) { + return Promise$1.all(args).then(function (args) { var result = tryApply(nodeFunc, self, args); if (result === ERROR) { reject(promise, result.value); @@ -1632,7 +1633,7 @@ function handlePromiseInput(promise, args, nodeFunc, self) { function needsPromiseInput(arg) { if (arg && typeof arg === 'object') { - if (arg.constructor === Promise) { + if (arg.constructor === Promise$1) { return true; } else { return getThen$1(arg); @@ -1652,8 +1653,8 @@ function needsPromiseInput(arg) { @param {String} label An optional label. This is useful for tooling. */ -function all$1(array, label) { - return Promise.all(array, label); +function all$3(array, label) { + return Promise$1.all(array, label); } function AllSettled(Constructor, entries, label) { @@ -1718,8 +1719,8 @@ AllSettled.prototype._validationError = function () { @return {Promise} promise that is fulfilled with an array of the settled states of the constituent promises. */ -function allSettled(entries, label) { - return new AllSettled(Promise, entries, label).promise; +function allSettled$1(entries, label) { + return new AllSettled(Promise$1, entries, label).promise; } /** @@ -1732,8 +1733,8 @@ function allSettled(entries, label) { @param {String} label An optional label. This is useful for tooling. */ -function race$1(array, label) { - return Promise.race(array, label); +function race$3(array, label) { + return Promise$1.race(array, label); } function PromiseHash(Constructor, object, label) { @@ -1867,8 +1868,8 @@ PromiseHash.prototype._enumerate = function () { @return {Promise} promise that is fulfilled when all properties of `promises` have been fulfilled, or rejected if any of them become rejected. */ -function hash(object, label) { - return new PromiseHash(Promise, object, label).promise; +function hash$1(object, label) { + return new PromiseHash(Promise$1, object, label).promise; } function HashSettled(Constructor, object, label) { @@ -1984,11 +1985,51 @@ HashSettled.prototype._validationError = function () { have been settled. @static */ -function hashSettled(object, label) { - return new HashSettled(Promise, object, label).promise; +function hashSettled$1(object, label) { + return new HashSettled(Promise$1, object, label).promise; } -function rethrow(reason) { +/** + `RSVP.rethrow` will rethrow an error on the next turn of the JavaScript event + loop in order to aid debugging. + + Promises A+ specifies that any exceptions that occur with a promise must be + caught by the promises implementation and bubbled to the last handler. For + this reason, it is recommended that you always specify a second rejection + handler function to `then`. However, `RSVP.rethrow` will throw the exception + outside of the promise, so it bubbles up to your console if in the browser, + or domain/cause uncaught exception in Node. `rethrow` will also throw the + error again so the error can be handled by the promise per the spec. + + ```javascript + function throws(){ + throw new Error('Whoops!'); + } + + let promise = new RSVP.Promise(function(resolve, reject){ + throws(); + }); + + promise.catch(RSVP.rethrow).then(function(){ + // Code here doesn't run because the promise became rejected due to an + // error! + }, function (err){ + // handle the error here + }); + ``` + + The 'Whoops' error will be thrown on the next turn of the event loop + and you can watch for it in your console. You can also handle it using a + rejection handler given to `.then` or `.catch` on the returned promise. + + @method rethrow + @static + @for RSVP + @param {Error} reason reason the promise became rejected. + @throws Error + @static +*/ +function rethrow$1(reason) { setTimeout(function () { throw reason; }); @@ -2027,10 +2068,10 @@ function rethrow(reason) { Useful for tooling. @return {Object} */ -function defer(label) { +function defer$1(label) { var deferred = { resolve: undefined, reject: undefined }; - deferred.promise = new Promise(function (resolve, reject) { + deferred.promise = new Promise$1(function (resolve, reject) { deferred.resolve = resolve; deferred.reject = reject; }, label); @@ -2116,8 +2157,8 @@ function defer(label) { The promise will be rejected if any of the given `promises` become rejected. @static */ -function map(promises, mapFn, label) { - return Promise.all(promises, label).then(function (values) { +function map$1(promises, mapFn, label) { + return Promise$1.all(promises, label).then(function (values) { if (!isFunction(mapFn)) { throw new TypeError("You must pass a function as map's second argument."); } @@ -2129,7 +2170,7 @@ function map(promises, mapFn, label) { results[i] = mapFn(values[i]); } - return Promise.all(results, label); + return Promise$1.all(results, label); }); } @@ -2145,8 +2186,8 @@ function map(promises, mapFn, label) { @return {Promise} a promise that will become fulfilled with the given `value` */ -function resolve$2(value, label) { - return Promise.resolve(value, label); +function resolve$3(value, label) { + return Promise$1.resolve(value, label); } /** @@ -2160,8 +2201,8 @@ function resolve$2(value, label) { Useful for tooling. @return {Promise} a promise rejected with the given `reason`. */ -function reject$2(reason, label) { - return Promise.reject(reason, label); +function reject$3(reason, label) { + return Promise$1.reject(reason, label); } /** @@ -2251,15 +2292,15 @@ function reject$2(reason, label) { */ function resolveAll(promises, label) { - return Promise.all(promises, label); + return Promise$1.all(promises, label); } function resolveSingle(promise, label) { - return Promise.resolve(promise, label).then(function (promises) { + return Promise$1.resolve(promise, label).then(function (promises) { return resolveAll(promises, label); }); } -function filter(promises, filterFn, label) { +function filter$1(promises, filterFn, label) { var promise = isArray(promises) ? resolveAll(promises, label) : resolveSingle(promises, label); return promise.then(function (values) { if (!isFunction(filterFn)) { @@ -2293,7 +2334,7 @@ function filter(promises, filterFn, label) { var len = 0; var vertxNext = undefined; -function asap(callback, arg) { +function asap$1(callback, arg) { queue$1[len] = callback; queue$1[len + 1] = arg; len += 2; @@ -2425,11 +2466,11 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope // the default export here is for backwards compat: // https://github.com/tildeio/rsvp.js/issues/434 -config.async = asap; +config.async = asap$1; config.after = function (cb) { return setTimeout(cb, 0); }; -var cast = resolve$2; +var cast = resolve$3; var async = function async(callback, arg) { return config.async(callback, arg); @@ -2453,55 +2494,59 @@ if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__' } } }var rsvp = (_async$filter = { + asap: asap$1, cast: cast, - Promise: Promise, + Promise: Promise$1, EventTarget: EventTarget, - all: all$1, - allSettled: allSettled, - race: race$1, - hash: hash, - hashSettled: hashSettled, - rethrow: rethrow, - defer: defer, - denodeify: denodeify, + all: all$3, + allSettled: allSettled$1, + race: race$3, + hash: hash$1, + hashSettled: hashSettled$1, + rethrow: rethrow$1, + defer: defer$1, + denodeify: denodeify$1, configure: configure, on: on, off: off, - resolve: resolve$2, - reject: reject$2, - map: map + resolve: resolve$3, + reject: reject$3, + map: map$1 }, _defineProperty(_async$filter, 'async', async), _defineProperty(_async$filter, 'filter', // babel seems to error if async isn't a computed prop here... -filter), _async$filter); +filter$1), _async$filter); exports['default'] = rsvp; +exports.asap = asap$1; exports.cast = cast; -exports.Promise = Promise; +exports.Promise = Promise$1; exports.EventTarget = EventTarget; -exports.all = all$1; -exports.allSettled = allSettled; -exports.race = race$1; -exports.hash = hash; -exports.hashSettled = hashSettled; -exports.rethrow = rethrow; -exports.defer = defer; -exports.denodeify = denodeify; +exports.all = all$3; +exports.allSettled = allSettled$1; +exports.race = race$3; +exports.hash = hash$1; +exports.hashSettled = hashSettled$1; +exports.rethrow = rethrow$1; +exports.defer = defer$1; +exports.denodeify = denodeify$1; exports.configure = configure; exports.on = on; exports.off = off; -exports.resolve = resolve$2; -exports.reject = reject$2; -exports.map = map; +exports.resolve = resolve$3; +exports.reject = reject$3; +exports.map = map$1; exports.async = async; -exports.filter = filter; +exports.filter = filter$1; Object.defineProperty(exports, '__esModule', { value: true }); }))); + // + 'use strict'; var EPUBJS = EPUBJS || {}; -EPUBJS.VERSION = "0.2.15"; +EPUBJS.VERSION = "0.2.19"; EPUBJS.plugins = EPUBJS.plugins || {}; @@ -2586,6 +2631,7 @@ EPUBJS.Book = function(options){ reload : false, goto : false, styles : {}, + classes : [], headTags : {}, withCredentials: false, render_method: "Iframe", @@ -3776,6 +3822,47 @@ EPUBJS.Book.prototype.removeStyle = function(style) { delete this.settings.styles[style]; }; +EPUBJS.Book.prototype.resetClasses = function(classes) { + + if(!this.isRendered) return this._q.enqueue("setClasses", arguments); + + if(classes.constructor === String) classes = [ classes ]; + + this.settings.classes = classes; + + this.renderer.setClasses(this.settings.classes); + this.renderer.reformat(); +}; + +EPUBJS.Book.prototype.addClass = function(aClass) { + + if(!this.isRendered) return this._q.enqueue("addClass", arguments); + + if(this.settings.classes.indexOf(aClass) == -1) { + this.settings.classes.push(aClass); + } + + this.renderer.setClasses(this.settings.classes); + this.renderer.reformat(); +}; + +EPUBJS.Book.prototype.removeClass = function(aClass) { + + if(!this.isRendered) return this._q.enqueue("removeClass", arguments); + + var idx = this.settings.classes.indexOf(aClass); + + if(idx != -1) { + + delete this.settings.classes[idx]; + + this.renderer.setClasses(this.settings.classes); + this.renderer.reformat(); + + } + +}; + EPUBJS.Book.prototype.addHeadTag = function(tag, attrs) { if(!this.isRendered) return this._q.enqueue("addHeadTag", arguments); this.settings.headTags[tag] = attrs; @@ -3874,6 +3961,12 @@ EPUBJS.Book.prototype.applyStyles = function(renderer, callback){ callback(); }; +EPUBJS.Book.prototype.applyClasses = function(renderer, callback){ + // if(!this.isRendered) return this._q.enqueue("applyClasses", arguments); + renderer.setClasses(this.settings.classes); + callback(); +}; + EPUBJS.Book.prototype.applyHeadTags = function(renderer, callback){ // if(!this.isRendered) return this._q.enqueue("applyHeadTags", arguments); renderer.applyHeadTags(this.settings.headTags); @@ -3883,6 +3976,7 @@ EPUBJS.Book.prototype.applyHeadTags = function(renderer, callback){ EPUBJS.Book.prototype._registerReplacements = function(renderer){ renderer.registerHook("beforeChapterDisplay", this.applyStyles.bind(this, renderer), true); renderer.registerHook("beforeChapterDisplay", this.applyHeadTags.bind(this, renderer), true); + renderer.registerHook("beforeChapterDisplay", this.applyClasses.bind(this, renderer), true); renderer.registerHook("beforeChapterDisplay", EPUBJS.replace.hrefs.bind(this), true); }; @@ -4089,7 +4183,7 @@ EPUBJS.Chapter.prototype.cfiFromRange = function(_range) { var range; var startXpath, endXpath; var startContainer, endContainer; - var cleanTextContent, cleanEndTextContent; + var cleanTextContent, cleanStartTextContent, cleanEndTextContent; // Check for Contents if(!this.document) return; @@ -4340,6 +4434,11 @@ EPUBJS.Chapter.prototype.replaceWithStored = function(query, attr, func, callbac var EPUBJS = EPUBJS || {}; EPUBJS.core = {}; +var ELEMENT_NODE = 1; +var TEXT_NODE = 3; +var COMMENT_NODE = 8; +var DOCUMENT_NODE = 9; + //-- Get a element for an id EPUBJS.core.getEl = function(elem) { return document.getElementById(elem); @@ -4512,7 +4611,7 @@ EPUBJS.core.uri = function(url){ if(search != -1) { uri.search = url.slice(search + 1); url = url.slice(0, search); - href = url; + href = uri.href; } if(doubleSlash != -1) { @@ -4964,13 +5063,37 @@ EPUBJS.core.values = function(object) { return result; }; +EPUBJS.core.indexOfNode = function(node, typeId) { + var parent = node.parentNode; + var children = parent.childNodes; + var sib; + var index = -1; + for (var i = 0; i < children.length; i++) { + sib = children[i]; + if (sib.nodeType === typeId) { + index++; + } + if (sib == node) break; + } + + return index; +} + +EPUBJS.core.indexOfTextNode = function(textNode) { + return EPUBJS.core.indexOfNode(textNode, TEXT_NODE); +} + +EPUBJS.core.indexOfElementNode = function(elementNode) { + return EPUBJS.core.indexOfNode(elementNode, ELEMENT_NODE); +} + EPUBJS.EpubCFI = function(cfiStr){ if(cfiStr) return this.parse(cfiStr); }; EPUBJS.EpubCFI.prototype.generateChapterComponent = function(_spineNodeIndex, _pos, id) { var pos = parseInt(_pos), - spineNodeIndex = _spineNodeIndex + 1, + spineNodeIndex = (_spineNodeIndex + 1) * 2, cfi = '/'+spineNodeIndex+'/'; cfi += (pos + 1) * 2; @@ -4983,20 +5106,9 @@ EPUBJS.EpubCFI.prototype.generateChapterComponent = function(_spineNodeIndex, _p }; EPUBJS.EpubCFI.prototype.generatePathComponent = function(steps) { - var parts = []; - - steps.forEach(function(part){ - var segment = ''; - segment += (part.index + 1) * 2; - - if(part.id) { - segment += "[" + part.id + "]"; - } - - parts.push(segment); - }); - - return parts.join('/'); + return steps.map(function(part) { + return (part.index + 1) * 2 + (part.id ? '[' + part.id + ']' : ''); + }).join('/'); }; EPUBJS.EpubCFI.prototype.generateCfiFromElement = function(element, chapter) { @@ -5007,7 +5119,7 @@ EPUBJS.EpubCFI.prototype.generateCfiFromElement = function(element, chapter) { return "epubcfi(" + chapter + "!/4/)"; } else { // First Text Node - return "epubcfi(" + chapter + "!" + path + "/1:0)"; + return "epubcfi(" + chapter + "!/" + path + "/1:0)"; } }; @@ -5352,7 +5464,7 @@ EPUBJS.EpubCFI.prototype.generateCfiFromTextNode = function(anchor, offset, base var steps = this.pathTo(parent); var path = this.generatePathComponent(steps); var index = 1 + (2 * Array.prototype.indexOf.call(parent.childNodes, anchor)); - return "epubcfi(" + base + "!" + path + "/"+index+":"+(offset || 0)+")"; + return "epubcfi(" + base + "!/" + path + "/"+index+":"+(offset || 0)+")"; }; EPUBJS.EpubCFI.prototype.generateCfiFromRangeAnchor = function(range, base) { @@ -5404,10 +5516,10 @@ EPUBJS.EpubCFI.prototype.generateCfiFromRange = function(range, base) { endPath = endPath + "/"; } - return "epubcfi(" + base + "!" + startPath + "/" + startIndex + ":" + startOffset + "," + endPath + endIndex + ":" + endOffset + ")"; + return "epubcfi(" + base + "!/" + startPath + "/" + startIndex + ":" + startOffset + "," + endPath + endIndex + ":" + endOffset + ")"; } else { - return "epubcfi(" + base + "!" + startPath + "/"+ startIndex +":"+ startOffset +")"; + return "epubcfi(" + base + "!/" + startPath + "/"+ startIndex +":"+ startOffset +")"; } }; @@ -5509,12 +5621,7 @@ EPUBJS.EpubCFI.prototype.generateRangeFromCfi = function(cfi, _doc) { }; EPUBJS.EpubCFI.prototype.isCfiString = function(target) { - if(typeof target === "string" && - target.indexOf("epubcfi(") === 0) { - return true; - } - - return false; + return typeof target === 'string' && target.indexOf('epubcfi(') === 0; }; EPUBJS.Events = function(obj, el){ @@ -5711,7 +5818,7 @@ EPUBJS.Layout.isFixedLayout = function (documentElement) { return false; } var content = viewport.getAttribute("content"); - return /,/.test(content); + return (/width=(\d+)/.test(content) && /height=(\d+)/.test(content)); }; EPUBJS.Layout.Reflowable = function(){ @@ -6465,24 +6572,23 @@ EPUBJS.Parser.prototype.manifest = function(manifestXml){ }; EPUBJS.Parser.prototype.spine = function(spineXml, manifest){ - var spine = []; - var selected = spineXml.getElementsByTagName("itemref"), items = Array.prototype.slice.call(selected); - var spineNodeIndex = Array.prototype.indexOf.call(spineXml.parentNode.childNodes, spineXml); + // var spineNodeIndex = Array.prototype.indexOf.call(spineXml.parentNode.childNodes, spineXml); + var spineNodeIndex = EPUBJS.core.indexOfElementNode(spineXml); var epubcfi = new EPUBJS.EpubCFI(); //-- Add to array to mantain ordering and cross reference with manifest - items.forEach(function(item, index){ + return items.map(function(item, index) { var Id = item.getAttribute('idref'); var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id); var props = item.getAttribute('properties') || ''; var propArray = props.length ? props.split(' ') : []; var manifestProps = manifest[Id].properties; var manifestPropArray = manifestProps.length ? manifestProps.split(' ') : []; - var vert = { + return { 'id' : Id, 'linear' : item.getAttribute('linear') || '', 'properties' : propArray, @@ -6493,10 +6599,7 @@ EPUBJS.Parser.prototype.spine = function(spineXml, manifest){ 'cfiBase' : cfiBase, 'cfi' : "epubcfi(" + cfiBase + ")" }; - spine.push(vert); }); - - return spine; }; EPUBJS.Parser.prototype.querySelectorByType = function(html, element, type){ @@ -6682,7 +6785,7 @@ EPUBJS.Render.Iframe = function() { //-- Build up any html needed EPUBJS.Render.Iframe.prototype.create = function(){ this.element = document.createElement('div'); - this.element.id = "epubjs-view:" + this.id + this.element.id = "epubjs-view:" + this.id; this.isMobile = navigator.userAgent.match(/(iPad|iPhone|iPod|Mobile|Android)/g); this.transform = EPUBJS.core.prefixed('transform'); @@ -6893,6 +6996,10 @@ EPUBJS.Render.Iframe.prototype.removeStyle = function(style){ }; +EPUBJS.Render.Iframe.prototype.setClasses = function(classes){ + if(this.bodyEl) this.bodyEl.className = classes.join(" "); +}; + EPUBJS.Render.Iframe.prototype.addHeadTag = function(tag, attrs, _doc) { var doc = _doc || this.document; var tagEl = doc.createElement(tag); @@ -7389,10 +7496,10 @@ EPUBJS.Renderer.prototype.remove = function() { this.removeEventListeners(); this.removeSelectionListeners(); } - - // clean container content - this.container.innerHtml = ""; -// this.container.removeChild(this.element); + + // clean container content + //this.container.innerHtml = ""; // not safe + this.container.removeChild(this.element); }; //-- STYLES @@ -7411,6 +7518,10 @@ EPUBJS.Renderer.prototype.removeStyle = function(style){ this.render.removeStyle(style); }; +EPUBJS.Renderer.prototype.setClasses = function(classes){ + this.render.setClasses(classes); +}; + //-- HEAD TAGS EPUBJS.Renderer.prototype.applyHeadTags = function(headTags) { for ( var headTag in headTags ) { @@ -8163,7 +8274,7 @@ EPUBJS.Renderer.prototype.resize = function(width, height, setSize){ EPUBJS.Renderer.prototype.onResized = function(e) { this.trigger('renderer:beforeResize'); - + var width = this.container.clientWidth; var height = this.container.clientHeight; @@ -8456,7 +8567,6 @@ EPUBJS.replace.cssImports = function (_store, base, text) { EPUBJS.replace.cssUrls = function(_store, base, text){ var deferred = new RSVP.defer(), - promises = [], matches = text.match(/url\(\'?\"?((?!data:)[^\'|^\"^\)]*)\'?\"?\)/g); if(!_store) return; @@ -8466,15 +8576,13 @@ EPUBJS.replace.cssUrls = function(_store, base, text){ return deferred.promise; } - matches.forEach(function(str){ + var promises = matches.map(function(str) { var full = EPUBJS.core.resolveUrl(base, str.replace(/url\(|[|\)|\'|\"]|\?.*$/g, '')); - var replaced = _store.getUrl(full).then(function(url){ + return _store.getUrl(full).then(function(url) { text = text.replace(str, 'url("'+url+'")'); }, function(reason) { deferred.reject(reason); }); - - promises.push(replaced); }); RSVP.all(promises).then(function(){ @@ -8772,6 +8880,13 @@ EPUBJS.Unarchiver.prototype.getXml = function(url, encoding){ then(function(text){ var parser = new DOMParser(); var mimeType = EPUBJS.core.getMimeType(url); + + // Remove byte order mark before parsing + // https://www.w3.org/International/questions/qa-byte-order-mark + if(text.charCodeAt(0) === 0xFEFF) { + text = text.slice(1); + } + return parser.parseFromString(text, mimeType); }); |