Multiple levels of TOC + meta info.
This commit is contained in:
131
src/epub.js
131
src/epub.js
@@ -101,15 +101,30 @@ class EpubOpf{
|
||||
<dc:rights>Please read the legal notice included in this e-book and/or check the copyright status in your country.</dc:rights>
|
||||
<dc:identifier id="pub-id">${m.metadata.book_id}</dc:identifier>
|
||||
<dc:title>${m.metadata.title}</dc:title>
|
||||
<dc:language>${m.metadata.language}</dc:language>\n`
|
||||
<dc:language>${m.metadata.language}</dc:language>
|
||||
`
|
||||
|
||||
if (m.metadata.description){
|
||||
cnt += ` <dc:description>${m.metadata.description}</dc:description>\n`
|
||||
}
|
||||
if (m.metadata.isbn){
|
||||
cnt += ` <dc:identifier id="isbn">${m.metadata.isbn}</dc:identifier>\n`
|
||||
let onixcode = m.metadata.isbn.length > 10 ? '15' : '02'
|
||||
cnt += ` <meta refines="#isbn" property="identifier-type" scheme="onix:codelist5">${onixcode}</meta>\n`
|
||||
}
|
||||
if (m.metadata.publisher){
|
||||
cnt += ` <dc:publisher>${m.metadata.publisher}</dc:publisher>\n`
|
||||
}
|
||||
if (m.metadata.cover_image){
|
||||
cnt += ` <meta content="cover-image" name="${m.metadata.cover_image}"/>\n`
|
||||
}
|
||||
// <dc:creator opf:file-as="Greatness, Georgia's" opf:role="aut">Lauren Baratz-Logsted</dc:creator>
|
||||
for (let s in m.metadata.subject){
|
||||
cnt += ` <dc:subject>${m.metadata.subject[s]}</dc:subject>\n`
|
||||
}
|
||||
for (let a in m.metadata.author){
|
||||
cnt += ` <dc:creator id="creator-${a}">${m.metadata.author[a]}</dc:creator>\n`
|
||||
cnt += ` <meta refines="#creator-${a}" property="role" schema="marc:relators">aut</meta>\n`
|
||||
}
|
||||
|
||||
cnt +=' </metadata>\n <manifest>\n'
|
||||
|
||||
@@ -141,11 +156,37 @@ class EpubNcx{
|
||||
|
||||
generate(){
|
||||
let m = this.meta
|
||||
let cnt = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
let max_depth = 0;
|
||||
let toc = ''
|
||||
for (let i = 0; i < m.toc.length; ++i) {
|
||||
let toc_item = m.toc[i]
|
||||
toc +=
|
||||
` <navPoint class="chapter" id="navpoint-${i}" playOrder="${i}">\n`
|
||||
+` <navLabel><text>${toc_item.label}</text></navLabel>\n`
|
||||
+` <content src="${toc_item.href}"/>\n`
|
||||
|
||||
if (max_depth < toc_item.depth) {
|
||||
max_depth = toc_item.depth
|
||||
}
|
||||
|
||||
let next_depth = 1
|
||||
if (i+1 < m.toc.length) {
|
||||
next_depth = m.toc[i+1].depth
|
||||
}
|
||||
|
||||
for (let current_dept = toc_item.depth;
|
||||
current_dept >= next_depth;
|
||||
current_dept--) {
|
||||
toc += ' </navPoint>\n'
|
||||
}
|
||||
}
|
||||
|
||||
return `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" xml:lang="en" version="2005-1">
|
||||
<head>
|
||||
<meta name="dtb:uid" content="${m.metadata.book_id}"/>
|
||||
<meta name="dtb:depth" content="2"/>
|
||||
<meta name="dtb:depth" content="${max_depth}"/>
|
||||
<meta name="dtb:totalPageCount" content="0"/>
|
||||
<meta name="dtb:maxPageNumber" content="0"/>
|
||||
</head>
|
||||
@@ -153,18 +194,10 @@ class EpubNcx{
|
||||
<text>${m.metadata.title}</text>
|
||||
</docTitle>
|
||||
<navMap>
|
||||
${toc}
|
||||
</navMap>
|
||||
</ncx>
|
||||
`
|
||||
for (let i in this.meta.toc){
|
||||
let toc_item = this.meta.toc[i]
|
||||
cnt +=
|
||||
` <navPoint class="chapter" id="navpoint-${i}" playOrder="${i}">\n`
|
||||
+` <navLabel><text>${toc_item.label}</text></navLabel>\n`
|
||||
+` <content src="${toc_item.filename}"/>\n`
|
||||
+' </navPoint>\n'
|
||||
}
|
||||
|
||||
cnt += ' </navMap>\n</ncx>\n'
|
||||
return cnt
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +210,35 @@ class EpubNav{
|
||||
|
||||
generate(){
|
||||
let m = this.meta
|
||||
let cnt = `<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
|
||||
let toc = ''
|
||||
for (let i = 0; i < m.toc.length; ++i){
|
||||
let toc_item = m.toc[i]
|
||||
toc += ` <li><a href="${toc_item.href}">${toc_item.label}</a>`
|
||||
|
||||
let next_depth = 1
|
||||
if (i+1 < m.toc.length){
|
||||
next_depth = m.toc[i+1].depth
|
||||
}
|
||||
let current_dept = toc_item.depth
|
||||
|
||||
if (current_dept == next_depth){
|
||||
toc += ' </li>\n'
|
||||
}
|
||||
else if (current_dept < next_depth){
|
||||
for (; current_dept < next_depth; current_dept++){
|
||||
toc += ' <ol>\n'
|
||||
}
|
||||
}
|
||||
else if (current_dept > next_depth){
|
||||
for (; current_dept > next_depth; current_dept--){
|
||||
toc += ' </li></ol>\n'
|
||||
}
|
||||
toc += ' </li>\n'
|
||||
}
|
||||
}
|
||||
|
||||
return `<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:epub="http://www.idpf.org/2007/ops">
|
||||
@@ -189,14 +250,12 @@ class EpubNav{
|
||||
<nav epub:type="toc" id="toc">
|
||||
<h2>Table Of Content</h2>
|
||||
<ol>
|
||||
${toc}
|
||||
</ol>
|
||||
</nav>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
for (let i in this.meta.toc){
|
||||
let toc_item = this.meta.toc[i]
|
||||
cnt += ` <li><a href="${toc_item.filename}">${toc_item.label}</a></li>\n`
|
||||
}
|
||||
|
||||
cnt += ' </ol>\n </nav>\n</body>\n</html>\n'
|
||||
return cnt
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,11 +263,14 @@ class EpubMeta{
|
||||
constructor() {
|
||||
this.metadata = {
|
||||
book_id: 'book_id',
|
||||
isbn: null,
|
||||
title: 'title',
|
||||
language: 'en',
|
||||
author: 'author',
|
||||
publisher: 'publisher',
|
||||
cover_image: 'cover.img'
|
||||
author: [],
|
||||
publisher: null,
|
||||
cover_image: null,
|
||||
subject: [],
|
||||
description: null
|
||||
}
|
||||
this.manifest = {}
|
||||
this.spine = []
|
||||
@@ -228,14 +290,23 @@ class EpubMeta{
|
||||
this.metadata.title = title
|
||||
}
|
||||
addAuthor(author){
|
||||
this.metadata.author = author
|
||||
this.metadata.author.push(author)
|
||||
}
|
||||
addPublisher(publisher){
|
||||
this.metadata.publisher = publisher
|
||||
}
|
||||
addSubject(subject){
|
||||
this.metadata.subject.push(subject)
|
||||
}
|
||||
addLanguage(lang){
|
||||
this.metadata.language = lang
|
||||
}
|
||||
addDescription(description){
|
||||
this.metadata.description = description
|
||||
}
|
||||
addIsbn(isbn){
|
||||
this.metadata.isbn = isbn
|
||||
}
|
||||
|
||||
addMetaData(){
|
||||
}
|
||||
@@ -275,11 +346,8 @@ class EpubMeta{
|
||||
}
|
||||
|
||||
addToc(filename, label, depth){
|
||||
if (filename in this.override){
|
||||
filename = this.override[filename].filename
|
||||
}
|
||||
this.toc.push({
|
||||
filename: filename,
|
||||
href: filename,
|
||||
label: label,
|
||||
depth: depth
|
||||
})
|
||||
@@ -327,7 +395,6 @@ class EpubWriter{
|
||||
|
||||
if (filename in this.meta.override){
|
||||
let o = this.meta.override[filename]
|
||||
filename = o.filename
|
||||
content = o.convert(content)
|
||||
}
|
||||
|
||||
|
||||
@@ -210,21 +210,30 @@ function fillMetadata(epub, book)
|
||||
{
|
||||
epub.meta.addTitle(book.book_info.title)
|
||||
epub.meta.addLanguage(book.book_info.language)
|
||||
epub.meta.addBookId(book.book_info.isbn)
|
||||
if (book.book_info.isbn){
|
||||
epub.meta.addBookId(book.book_info.isbn)
|
||||
}
|
||||
if (book.book_info.description){
|
||||
epub.meta.addDescription(book.book_info.description)
|
||||
}
|
||||
epub.meta.addIsbn(book.book_info.isbn)
|
||||
for (let i in book.book_info.authors){
|
||||
let author = book.book_info.authors[i]
|
||||
epub.meta.addAuthor(author)
|
||||
epub.meta.addAuthor(author.name)
|
||||
}
|
||||
for (let i in book.book_info.publishers){
|
||||
let publisher = book.book_info.publishers[i]
|
||||
epub.meta.addPublisher(publisher.name)
|
||||
}
|
||||
for (let i in book.book_info.subjects){
|
||||
let subject = book.book_info.subjects[i]
|
||||
epub.meta.addSubject(subject.name)
|
||||
}
|
||||
|
||||
// # The metadata element or deprecated dc-metadata element contains
|
||||
// # at least one identifier element, at least one title element,
|
||||
// # and at least one language element drawn from the Dublin Core tag
|
||||
// # set.
|
||||
// epub.set_title('Test Title')
|
||||
// epub.set_language('en')
|
||||
// epub.set_direction('ltr')
|
||||
// # epub.set_cover(file_name, content, create_page=True):
|
||||
// # epub.add_author(author, file_as=None, role=None, uid='creator'):
|
||||
@@ -259,13 +268,19 @@ function fillHtmlComponents(epub, book)
|
||||
|
||||
function fillToc(epub, book)
|
||||
{
|
||||
for (let i in book.book_toc){
|
||||
let toc_item = book.book_toc[i]
|
||||
epub.meta.addToc(
|
||||
toc_item.filename,
|
||||
toc_item.label,
|
||||
toc_item.depth)
|
||||
let helper = function(epub, book_toc){
|
||||
for (let i in book_toc){
|
||||
let toc_item = book_toc[i]
|
||||
epub.meta.addToc(
|
||||
toc_item.href,
|
||||
toc_item.label,
|
||||
toc_item.depth)
|
||||
if ('children' in toc_item) {
|
||||
helper(epub, toc_item.children)
|
||||
}
|
||||
}
|
||||
}
|
||||
helper(epub,book.book_toc)
|
||||
}
|
||||
|
||||
function fillSpine(epub, book)
|
||||
@@ -277,24 +292,22 @@ function fillSpine(epub, book)
|
||||
}
|
||||
}
|
||||
|
||||
function fillGuide(epub, book)
|
||||
{}
|
||||
|
||||
function createEpub(book, epub){
|
||||
function createEpubStructure(book, epub){
|
||||
epub.addMetaInfoFile("book.json", JSON.stringify(book, null, '\t'))
|
||||
|
||||
// OPF file info.
|
||||
fillManifest(epub, book)
|
||||
fillSpine(epub, book)
|
||||
fillGuide(epub, book)
|
||||
fillMetadata(epub, book)
|
||||
|
||||
// NCX and NAV files.
|
||||
fillToc(epub, book)
|
||||
|
||||
fillHtmlComponents(epub, book)
|
||||
}
|
||||
|
||||
for (let url in book.book_files){
|
||||
function createEpub(book, epub){
|
||||
for (let url in book.book_files){
|
||||
file = book.book_files[url]
|
||||
epub.addFile(file.filename, file.body)
|
||||
}
|
||||
@@ -316,6 +329,7 @@ function onDownloadBookClicked(){
|
||||
// .then(() => { return page.renderChapterList(book); })
|
||||
.then(() => { return book.downloadMetaContent(); })
|
||||
.then(() => { return book.downloadContent(); })
|
||||
.then(() => { return createEpubStructure(book, epub); })
|
||||
.then(() => { return createEpub(book, epub); })
|
||||
.then(() => { return epub.generateAsync(); })
|
||||
.then((file) => {
|
||||
|
||||
Reference in New Issue
Block a user