1
0
Fork 0
mirror of https://github.com/futurepress/epub.js.git synced 2025-10-05 15:32:55 +02:00

add EPUB3 HTML TOC support

This commit is contained in:
Philip Schatz 2013-10-30 02:03:36 -04:00
parent deb69604c0
commit caa3c7d8f6
2 changed files with 88 additions and 2 deletions

View file

@ -197,8 +197,20 @@ EPUBJS.Book.prototype.unpack = function(containerPath){
//-- Adjust setting based on metadata
//-- Load the TOC, optional
if(contents.tocPath) {
//-- Load the TOC, optional; either the EPUB3 XHTML Navigation file or the EPUB2 NCX file
if(contents.navPath) {
book.settings.navUrl = book.settings.contentsPath + contents.navPath;
book.loadXml(book.settings.navUrl).
then(function(navHtml){
return parse.nav(navHtml); // Grab Table of Contents
}).then(function(toc){
book.toc = book.contents.toc = toc;
book.ready.toc.resolve(book.contents.toc);
});
} else if(contents.tocPath) {
book.settings.tocUrl = book.settings.contentsPath + contents.tocPath;

View file

@ -26,6 +26,7 @@ EPUBJS.Parser.prototype.package = function(packageXml, baseUrl){
spineNode = packageXml.querySelector("spine");
var manifest = parse.manifest(manifestNode),
navPath = parse.findNavPath(manifestNode),
tocPath = parse.findTocPath(manifestNode),
coverPath = parse.findCoverPath(manifestNode);
@ -42,6 +43,7 @@ EPUBJS.Parser.prototype.package = function(packageXml, baseUrl){
'metadata' : parse.metadata(metadataNode),
'spine' : spine,
'manifest' : manifest,
'navPath' : navPath,
'tocPath' : tocPath,
'coverPath': coverPath,
'spineNodeIndex' : spineNodeIndex,
@ -49,6 +51,12 @@ EPUBJS.Parser.prototype.package = function(packageXml, baseUrl){
};
}
//-- Find TOC NAV: media-type="application/xhtml+xml" href="toc.ncx"
EPUBJS.Parser.prototype.findNavPath = function(manifestNode){
var node = manifestNode.querySelector("item[properties^='nav']");
return node ? node.getAttribute('href') : false;
}
//-- Find TOC NCX: media-type="application/x-dtbncx+xml" href="toc.ncx"
EPUBJS.Parser.prototype.findTocPath = function(manifestNode){
var node = manifestNode.querySelector("item[media-type='application/x-dtbncx+xml']");
@ -167,6 +175,72 @@ EPUBJS.Parser.prototype.spine = function(spineXml, manifest){
return spine;
}
EPUBJS.Parser.prototype.nav = function(navHtml){
var navEl = navHtml.querySelector('nav[*|type="toc"]'),
idCounter = 0;
// Implements `> ol > li`
function findListItems(parent){
var items = [];
Array.prototype.slice.call(parent.childNodes).forEach(function(node){
if('ol' == node.tagName){
Array.prototype.slice.call(node.childNodes).forEach(function(item){
if('li' == item.tagName){
items.push(item);
}
})
}
})
return items;
}
// Implements `> a, > span`
function findAnchorOrSpan(parent){
var item = null;
Array.prototype.slice.call(parent.childNodes).forEach(function(node){
if('a' == node.tagName || 'span' == node.tagName){
item = node;
}
})
return item;
}
function getTOC(parent){
var list = [],
items = [],
nodes = findListItems(parent),
items = Array.prototype.slice.call(nodes),
length = items.length,
node;
if(length == 0) return false;
items.forEach(function(item){
var id = item.getAttribute('id') || 'epubjs-autogen-toc-id-' + (idCounter++),
content = findAnchorOrSpan(item),
href = content.getAttribute('href') || '',
text = content.textContent || "",
subitems = getTOC(item);
item.setAttribute('id', id); // Ensure all elements have an id
list.unshift({
"id": id,
"href": href,
"label": text,
"subitems" : subitems,
"parent" : parent ? parent.getAttribute('id') : null
});
});
return list;
}
return getTOC(navEl);
}
EPUBJS.Parser.prototype.toc = function(tocXml){
var navMap = tocXml.querySelector("navMap");