UNPKG

epubjs

Version:
162 lines (128 loc) 3.56 kB
import EpubCFI from "./epubcfi"; import Hook from "./utils/hook"; import Section from "./section"; import {replaceBase, replaceCanonical} from "./utils/replacements"; /** * A collection of Spine Items */ class Spine { constructor() { this.spineItems = []; this.spineByHref = {}; this.spineById = {}; this.hooks = {}; this.hooks.serialize = new Hook(); this.hooks.content = new Hook(); // Register replacements this.hooks.content.register(replaceBase); this.hooks.content.register(replaceCanonical); this.epubcfi = new EpubCFI(); this.loaded = false; } /** * Unpack items from a opf into spine items * @param {Package} _package * @param {method} resolver URL resolver */ unpack(_package, resolver) { this.items = _package.spine; this.manifest = _package.manifest; this.spineNodeIndex = _package.spineNodeIndex; this.baseUrl = _package.baseUrl || _package.basePath || ""; this.length = this.items.length; this.items.forEach( (item, index) => { var manifestItem = this.manifest[item.idref]; var spineItem; item.cfiBase = this.epubcfi.generateChapterComponent(this.spineNodeIndex, item.index, item.idref); if(manifestItem) { item.href = manifestItem.href; item.url = resolver(item.href, true); if(manifestItem.properties.length){ item.properties.push.apply(item.properties, manifestItem.properties); } } item.prev = function(){ return this.get(index-1); }.bind(this); item.next = function(){ return this.get(index+1); }.bind(this); spineItem = new Section(item, this.hooks); this.append(spineItem); }); this.loaded = true; } /** * Get an item from the spine * @param {[string|int]} target * @return {Section} section * @example spine.get(); * @example spine.get(1); * @example spine.get("chap1.html"); * @example spine.get("#id1234"); */ get(target) { var index = 0; if(this.epubcfi.isCfiString(target)) { let cfi = new EpubCFI(target); index = cfi.spinePos; } else if(target && (typeof target === "number" || isNaN(target) === false)){ index = target; } else if(target && target.indexOf("#") === 0) { index = this.spineById[target.substring(1)]; } else if(target) { // Remove fragments target = target.split("#")[0]; index = this.spineByHref[target]; } return this.spineItems[index] || null; } /** * Append a Section to the Spine * @private * @param {Section} section */ append(section) { var index = this.spineItems.length; section.index = index; this.spineItems.push(section); this.spineByHref[section.href] = index; this.spineById[section.idref] = index; return index; } /** * Prepend a Section to the Spine * @private * @param {Section} section */ prepend(section) { // var index = this.spineItems.unshift(section); this.spineByHref[section.href] = 0; this.spineById[section.idref] = 0; // Re-index this.spineItems.forEach(function(item, index){ item.index = index; }); return 0; } // insert(section, index) { // // }; /** * Remove a Section from the Spine * @private * @param {Section} section */ remove(section) { var index = this.spineItems.indexOf(section); if(index > -1) { delete this.spineByHref[section.href]; delete this.spineById[section.idref]; return this.spineItems.splice(index, 1); } } /** * Loop over the Sections in the Spine * @return {method} forEach */ each() { return this.spineItems.forEach.apply(this.spineItems, arguments); } } export default Spine;