mirror of
https://github.com/daniel-j/fimfic2epub.git
synced 2024-05-19 03:42:54 +12:00
edit description, put author notes in the end of the ebook
This commit is contained in:
parent
74ccaf1123
commit
7059fa2be5
|
@ -40,6 +40,10 @@ ffc.fetchAll()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log('Error: ' + (err || 'Unknown error'))
|
if (err && err.stack) {
|
||||||
|
console.error(err.stack)
|
||||||
|
} else {
|
||||||
|
console.error('Error: ' + (err || 'Unknown error'))
|
||||||
|
}
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,22 @@
|
||||||
|
|
||||||
|
/* checkbox fixes */
|
||||||
|
.toggleable-switch {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.toggleable-switch > a, .toggleable-switch > span {
|
||||||
|
transition: background 0.2s, opacity 0.2s !important;
|
||||||
|
}
|
||||||
|
.toggleable-switch input:disabled+a, .toggleable-switch input:disabled~span {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
.toggleable-switch input:disabled+a, .toggleable-switch input:checked:disabled+a {
|
||||||
|
background: #BBB;
|
||||||
|
}
|
||||||
|
.toggleable-switch input:disabled+a:before, .toggleable-switch input:checked:disabled+a:before {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the logo button */
|
||||||
.fimfic2epub-logo {
|
.fimfic2epub-logo {
|
||||||
float: right;
|
float: right;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
|
@ -24,6 +42,7 @@
|
||||||
width: 24px;
|
width: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* dialog popup */
|
||||||
#epubDialogContainer .drop-down-pop-up-container {
|
#epubDialogContainer .drop-down-pop-up-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"name": "fimfic2epub",
|
"name": "fimfic2epub",
|
||||||
"short_name": "fimfic2epub",
|
"short_name": "fimfic2epub",
|
||||||
"description": "Improved EPUB exporter for Fimfiction",
|
"description": "Improved EPUB exporter for Fimfiction",
|
||||||
"version": "1.4.4",
|
"version": "1.4.5",
|
||||||
|
|
||||||
"icons": {
|
"icons": {
|
||||||
"128": "icon-128.png"
|
"128": "icon-128.png"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "fimfic2epub",
|
"name": "fimfic2epub",
|
||||||
"version": "1.4.4",
|
"version": "1.4.5",
|
||||||
"description": "Tool to generate improved EPUB ebooks from Fimfiction stories",
|
"description": "Tool to generate improved EPUB ebooks from Fimfiction stories",
|
||||||
"author": "djazz",
|
"author": "djazz",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|
|
@ -88,6 +88,7 @@ class FimFic2Epub extends Emitter {
|
||||||
this.options = {
|
this.options = {
|
||||||
addCommentsLink: true,
|
addCommentsLink: true,
|
||||||
includeAuthorNotes: true,
|
includeAuthorNotes: true,
|
||||||
|
useAuthorNotesIndex: false,
|
||||||
addChapterHeadings: true,
|
addChapterHeadings: true,
|
||||||
includeExternal: true,
|
includeExternal: true,
|
||||||
|
|
||||||
|
@ -108,6 +109,9 @@ class FimFic2Epub extends Emitter {
|
||||||
this.subjects = []
|
this.subjects = []
|
||||||
this.chapters = []
|
this.chapters = []
|
||||||
this.chaptersHtml = []
|
this.chaptersHtml = []
|
||||||
|
this.notesHtml = []
|
||||||
|
this.hasAuthorNotes = false
|
||||||
|
this.chaptersWithNotes = []
|
||||||
this.remoteResourcesCached = false
|
this.remoteResourcesCached = false
|
||||||
this.remoteResources = new Map()
|
this.remoteResources = new Map()
|
||||||
this.coverUrl = ''
|
this.coverUrl = ''
|
||||||
|
@ -189,6 +193,8 @@ class FimFic2Epub extends Emitter {
|
||||||
}
|
}
|
||||||
this.chapters.length = 0
|
this.chapters.length = 0
|
||||||
this.chaptersHtml.length = 0
|
this.chaptersHtml.length = 0
|
||||||
|
this.hasAuthorNotes = false
|
||||||
|
this.chaptersWithNotes.length = 0
|
||||||
|
|
||||||
this.progress(0, 0, 'Fetching chapters...')
|
this.progress(0, 0, 'Fetching chapters...')
|
||||||
this.pcache.chapters = new Promise((resolve, reject) => {
|
this.pcache.chapters = new Promise((resolve, reject) => {
|
||||||
|
@ -218,6 +224,10 @@ class FimFic2Epub extends Emitter {
|
||||||
]).then((values) => {
|
]).then((values) => {
|
||||||
chapter.content = values[0]
|
chapter.content = values[0]
|
||||||
chapter.notes = values[1]
|
chapter.notes = values[1]
|
||||||
|
if (chapter.notes) {
|
||||||
|
this.hasAuthorNotes = true
|
||||||
|
this.chaptersWithNotes.push(index)
|
||||||
|
}
|
||||||
ch.realWordCount = htmlWordCount(chapter.content)
|
ch.realWordCount = htmlWordCount(chapter.content)
|
||||||
this.chapters[index] = chapter
|
this.chapters[index] = chapter
|
||||||
|
|
||||||
|
@ -226,6 +236,7 @@ class FimFic2Epub extends Emitter {
|
||||||
if (completeCount < chapterCount) {
|
if (completeCount < chapterCount) {
|
||||||
recursive()
|
recursive()
|
||||||
} else {
|
} else {
|
||||||
|
this.chaptersWithNotes.sort((a, b) => a - b)
|
||||||
resolve()
|
resolve()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -303,14 +314,31 @@ class FimFic2Epub extends Emitter {
|
||||||
buildChapters () {
|
buildChapters () {
|
||||||
let chain = Promise.resolve()
|
let chain = Promise.resolve()
|
||||||
this.chaptersHtml.length = 0
|
this.chaptersHtml.length = 0
|
||||||
|
this.notesHtml.length = 0
|
||||||
|
|
||||||
for (let i = 0; i < this.chapters.length; i++) {
|
for (let i = 0; i < this.chapters.length; i++) {
|
||||||
let ch = this.storyInfo.chapters[i]
|
let ch = this.storyInfo.chapters[i]
|
||||||
let chapter = this.chapters[i]
|
let chapter = this.chapters[i]
|
||||||
chain = chain.then(template.createChapter.bind(null, ch, chapter, this)).then((html) => {
|
chain = chain.then(template.createChapter.bind(null, {
|
||||||
this.findRemoteResources('ch_' + zeroFill(3, i + 1), i, html)
|
title: this.options.addChapterHeadings ? ch.title : null,
|
||||||
|
link: this.options.addCommentsLink ? ch.link : null,
|
||||||
|
linkNotes: this.options.includeAuthorNotes && this.options.useAuthorNotesIndex && chapter.notes ? 'note_' + zeroFill(3, i + 1) + '.xhtml' : null,
|
||||||
|
content: chapter.content,
|
||||||
|
notes: !this.options.useAuthorNotesIndex ? chapter.notes : '',
|
||||||
|
notesFirst: chapter.notesFirst
|
||||||
|
})).then((html) => {
|
||||||
|
this.findRemoteResources('ch_' + zeroFill(3, i + 1), {chapter: i}, html)
|
||||||
this.chaptersHtml[i] = html
|
this.chaptersHtml[i] = html
|
||||||
})
|
})
|
||||||
|
if (this.options.includeAuthorNotes && this.options.useAuthorNotesIndex && chapter.notes) {
|
||||||
|
chain = chain.then(template.createChapter.bind(null, {
|
||||||
|
title: 'Author\'s Note: ' + ch.title,
|
||||||
|
content: chapter.notes
|
||||||
|
})).then((html) => {
|
||||||
|
this.findRemoteResources('note_' + zeroFill(3, i + 1), {note: i}, html)
|
||||||
|
this.notesHtml[i] = html
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return chain
|
return chain
|
||||||
|
@ -338,7 +366,7 @@ class FimFic2Epub extends Emitter {
|
||||||
this.zip.file('OEBPS/Text/title.xhtml', template.createTitlePage(this))
|
this.zip.file('OEBPS/Text/title.xhtml', template.createTitlePage(this))
|
||||||
this.zip.file('OEBPS/Styles/titlestyle.css', titlestyleCss)
|
this.zip.file('OEBPS/Styles/titlestyle.css', titlestyleCss)
|
||||||
|
|
||||||
this.zip.file('OEBPS/Text/nav.xhtml', template.createNav(this))
|
this.zip.file('OEBPS/Text/nav.xhtml', template.createNav(this, 0))
|
||||||
this.zip.file('OEBPS/toc.ncx', template.createNcx(this))
|
this.zip.file('OEBPS/toc.ncx', template.createNcx(this))
|
||||||
|
|
||||||
for (let i = 0; i < this.chapters.length; i++) {
|
for (let i = 0; i < this.chapters.length; i++) {
|
||||||
|
@ -347,6 +375,17 @@ class FimFic2Epub extends Emitter {
|
||||||
this.zip.file(filename, html)
|
this.zip.file(filename, html)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.options.includeAuthorNotes && this.options.useAuthorNotesIndex && this.hasAuthorNotes) {
|
||||||
|
this.zip.file('OEBPS/Text/notesnav.xhtml', template.createNav(this, 1))
|
||||||
|
|
||||||
|
for (let i = 0; i < this.chapters.length; i++) {
|
||||||
|
if (!this.chapters[i].notes) continue
|
||||||
|
let filename = 'OEBPS/Text/note_' + zeroFill(3, i + 1) + '.xhtml'
|
||||||
|
let html = this.notesHtml[i]
|
||||||
|
this.zip.file(filename, html)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.zip.file('OEBPS/Styles/style.css', styleCss)
|
this.zip.file('OEBPS/Styles/style.css', styleCss)
|
||||||
|
|
||||||
this.remoteResources.forEach((r) => {
|
this.remoteResources.forEach((r) => {
|
||||||
|
@ -617,8 +656,10 @@ class FimFic2Epub extends Emitter {
|
||||||
let ourl = new RegExp(escapeStringRegexp(r.originalUrl), 'g')
|
let ourl = new RegExp(escapeStringRegexp(r.originalUrl), 'g')
|
||||||
for (var i = 0; i < r.where.length; i++) {
|
for (var i = 0; i < r.where.length; i++) {
|
||||||
let w = r.where[i]
|
let w = r.where[i]
|
||||||
if (typeof w === 'number') {
|
if (typeof w === 'object' && w.chapter !== undefined && this.chaptersHtml[w.chapter]) {
|
||||||
this.chaptersHtml[w] = this.chaptersHtml[w].replace(ourl, dest)
|
this.chaptersHtml[w.chapter] = this.chaptersHtml[w.chapter].replace(ourl, dest)
|
||||||
|
} else if (typeof w === 'object' && w.note !== undefined && this.notesHtml[w.note]) {
|
||||||
|
this.notesHtml[w.note] = this.notesHtml[w.note].replace(ourl, dest)
|
||||||
} else if (w === 'description') {
|
} else if (w === 'description') {
|
||||||
this.storyInfo.description = this.storyInfo.description.replace(ourl, dest)
|
this.storyInfo.description = this.storyInfo.description.replace(ourl, dest)
|
||||||
} else if (w === 'tags') {
|
} else if (w === 'tags') {
|
||||||
|
|
24
src/main.js
24
src/main.js
|
@ -79,10 +79,12 @@ document.body.appendChild(dialogContainer)
|
||||||
|
|
||||||
let checkbox = {
|
let checkbox = {
|
||||||
view: function (ctrl, args, text) {
|
view: function (ctrl, args, text) {
|
||||||
return m('label.toggleable-switch', {style: 'white-space: nowrap;'}, [
|
return m('label.toggleable-switch', [
|
||||||
m('input', {type: 'checkbox', name: args.name, checked: args.checked, onchange: args.onchange}),
|
m('input', Object.assign({
|
||||||
m('a', {style: 'margin-right: 10px'}),
|
type: 'checkbox'
|
||||||
text
|
}, args)),
|
||||||
|
m('a'),
|
||||||
|
text ? m('span', text) : null
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,9 +109,11 @@ let dialog = {
|
||||||
|
|
||||||
this.title = m.prop('')
|
this.title = m.prop('')
|
||||||
this.author = m.prop('')
|
this.author = m.prop('')
|
||||||
|
this.description = m.prop('')
|
||||||
this.subjects = m.prop([])
|
this.subjects = m.prop([])
|
||||||
this.addCommentsLink = m.prop(ffc.options.addCommentsLink)
|
this.addCommentsLink = m.prop(ffc.options.addCommentsLink)
|
||||||
this.includeAuthorNotes = m.prop(ffc.options.includeAuthorNotes)
|
this.includeAuthorNotes = m.prop(ffc.options.includeAuthorNotes)
|
||||||
|
this.useAuthorNotesIndex = m.prop(ffc.options.useAuthorNotesIndex)
|
||||||
this.addChapterHeadings = m.prop(ffc.options.addChapterHeadings)
|
this.addChapterHeadings = m.prop(ffc.options.addChapterHeadings)
|
||||||
this.includeExternal = m.prop(ffc.options.includeExternal)
|
this.includeExternal = m.prop(ffc.options.includeExternal)
|
||||||
this.joinSubjects = m.prop(ffc.options.joinSubjects)
|
this.joinSubjects = m.prop(ffc.options.joinSubjects)
|
||||||
|
@ -124,6 +128,7 @@ let dialog = {
|
||||||
ffcProgress(-1)
|
ffcProgress(-1)
|
||||||
this.title(ffc.storyInfo.title)
|
this.title(ffc.storyInfo.title)
|
||||||
this.author(ffc.storyInfo.author.name)
|
this.author(ffc.storyInfo.author.name)
|
||||||
|
this.description(ffc.storyInfo.short_description)
|
||||||
this.subjects(ffc.subjects.slice(0))
|
this.subjects(ffc.subjects.slice(0))
|
||||||
m.redraw(true)
|
m.redraw(true)
|
||||||
this.center()
|
this.center()
|
||||||
|
@ -152,6 +157,12 @@ let dialog = {
|
||||||
autosize.update(this)
|
autosize.update(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.setDescription = function () {
|
||||||
|
ctrl.description(this.value.trim())
|
||||||
|
this.value = ctrl.description()
|
||||||
|
autosize.update(this)
|
||||||
|
}
|
||||||
|
|
||||||
this.ondown = (e) => {
|
this.ondown = (e) => {
|
||||||
let rect = this.el().firstChild.getBoundingClientRect()
|
let rect = this.el().firstChild.getBoundingClientRect()
|
||||||
let offset = {x: e.pageX - rect.left - document.body.scrollLeft, y: e.pageY - rect.top - document.body.scrollTop}
|
let offset = {x: e.pageX - rect.left - document.body.scrollLeft, y: e.pageY - rect.top - document.body.scrollTop}
|
||||||
|
@ -202,8 +213,10 @@ let dialog = {
|
||||||
}
|
}
|
||||||
ffc.setTitle(this.title())
|
ffc.setTitle(this.title())
|
||||||
ffc.setAuthorName(this.author())
|
ffc.setAuthorName(this.author())
|
||||||
|
ffc.storyInfo.short_description = this.description()
|
||||||
ffc.options.addCommentsLink = this.addCommentsLink()
|
ffc.options.addCommentsLink = this.addCommentsLink()
|
||||||
ffc.options.includeAuthorNotes = this.includeAuthorNotes()
|
ffc.options.includeAuthorNotes = this.includeAuthorNotes()
|
||||||
|
ffc.options.useAuthorNotesIndex = this.useAuthorNotesIndex()
|
||||||
ffc.options.addChapterHeadings = this.addChapterHeadings()
|
ffc.options.addChapterHeadings = this.addChapterHeadings()
|
||||||
ffc.options.includeExternal = this.includeExternal()
|
ffc.options.includeExternal = this.includeExternal()
|
||||||
ffc.subjects = this.subjects()
|
ffc.subjects = this.subjects()
|
||||||
|
@ -214,7 +227,6 @@ let dialog = {
|
||||||
.then(ffc.fetchAll.bind(ffc))
|
.then(ffc.fetchAll.bind(ffc))
|
||||||
.then(ffc.build.bind(ffc))
|
.then(ffc.build.bind(ffc))
|
||||||
.then(ffc.getFile.bind(ffc)).then((file) => {
|
.then(ffc.getFile.bind(ffc)).then((file) => {
|
||||||
console.log('Saving file...')
|
|
||||||
if (typeof safari !== 'undefined') {
|
if (typeof safari !== 'undefined') {
|
||||||
blobToDataURL(file).then((dataurl) => {
|
blobToDataURL(file).then((dataurl) => {
|
||||||
document.location.href = dataurl
|
document.location.href = dataurl
|
||||||
|
@ -245,11 +257,13 @@ let dialog = {
|
||||||
m(checkbox, {checked: ctrl.addChapterHeadings(), onchange: m.withAttr('checked', ctrl.addChapterHeadings)}, 'Add chapter headings'),
|
m(checkbox, {checked: ctrl.addChapterHeadings(), onchange: m.withAttr('checked', ctrl.addChapterHeadings)}, 'Add chapter headings'),
|
||||||
m(checkbox, {checked: ctrl.addCommentsLink(), onchange: m.withAttr('checked', ctrl.addCommentsLink)}, 'Add link to online comments (at the end of chapters)'),
|
m(checkbox, {checked: ctrl.addCommentsLink(), onchange: m.withAttr('checked', ctrl.addCommentsLink)}, 'Add link to online comments (at the end of chapters)'),
|
||||||
m(checkbox, {checked: ctrl.includeAuthorNotes(), onchange: m.withAttr('checked', ctrl.includeAuthorNotes)}, 'Include author\'s notes'),
|
m(checkbox, {checked: ctrl.includeAuthorNotes(), onchange: m.withAttr('checked', ctrl.includeAuthorNotes)}, 'Include author\'s notes'),
|
||||||
|
m(checkbox, {checked: ctrl.useAuthorNotesIndex(), onchange: m.withAttr('checked', ctrl.useAuthorNotesIndex), disabled: !ctrl.includeAuthorNotes()}, 'Put all notes at the end of the ebook'),
|
||||||
m(checkbox, {checked: ctrl.includeExternal(), onchange: m.withAttr('checked', ctrl.includeExternal)}, 'Download & include remote content (embed images)'),
|
m(checkbox, {checked: ctrl.includeExternal(), onchange: m.withAttr('checked', ctrl.includeExternal)}, 'Download & include remote content (embed images)'),
|
||||||
m('div', {style: 'font-size: 0.9em; line-height: 1em; margin-top: 4px; margin-bottom: 6px; color: #777;'}, 'Note: Disabling this creates invalid EPUBs and requires internet access to see remote content. Only cover image will be embedded.')
|
m('div', {style: 'font-size: 0.9em; line-height: 1em; margin-top: 4px; margin-bottom: 6px; color: #777;'}, 'Note: Disabling this creates invalid EPUBs and requires internet access to see remote content. Only cover image will be embedded.')
|
||||||
)),
|
)),
|
||||||
|
|
||||||
m('tr', m('td.section_header', {colspan: 3}, m('b', 'Metadata customization'))),
|
m('tr', m('td.section_header', {colspan: 3}, m('b', 'Metadata customization'))),
|
||||||
|
m('tr', m('td.label', {style: 'vertical-align: top;'}, 'Description'), m('td', {colspan: 2}, m('textarea', {config: autosize, onchange: ctrl.setDescription}, ctrl.description()))),
|
||||||
m('tr', m('td.label', {style: 'vertical-align: top;'}, 'Categories'), m('td', {colspan: 2},
|
m('tr', m('td.label', {style: 'vertical-align: top;'}, 'Categories'), m('td', {colspan: 2},
|
||||||
m('textarea', {rows: 2, config: autosize, onchange: ctrl.setSubjects}, ctrl.subjects().join('\n')),
|
m('textarea', {rows: 2, config: autosize, onchange: ctrl.setSubjects}, ctrl.subjects().join('\n')),
|
||||||
m(checkbox, {checked: ctrl.joinSubjects(), onchange: m.withAttr('checked', ctrl.joinSubjects)}, 'Join categories and separate with commas (for iBooks only)')
|
m(checkbox, {checked: ctrl.joinSubjects(), onchange: m.withAttr('checked', ctrl.joinSubjects)}, 'Join categories and separate with commas (for iBooks only)')
|
||||||
|
|
105
src/templates.js
105
src/templates.js
|
@ -22,19 +22,19 @@ function prettyDate (d) {
|
||||||
return d.getDate() + nth(d) + ' ' + months[d.getMonth()].substring(0, 3) + ' ' + d.getFullYear()
|
return d.getDate() + nth(d) + ' ' + months[d.getMonth()].substring(0, 3) + ' ' + d.getFullYear()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createChapter (ch, chapter, ffc) {
|
export function createChapter (ch) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let {content, notes} = chapter
|
let {content, notes, notesFirst, title, link, linkNotes} = ch
|
||||||
|
|
||||||
let sections = [
|
let sections = [
|
||||||
m.trust(content),
|
m.trust(content || ''),
|
||||||
ffc.options.includeAuthorNotes && notes ? m('div#author_notes', {className: chapter.notesFirst ? 'top' : 'bottom'}, [
|
notes ? m('div#author_notes', {className: notesFirst ? 'top' : 'bottom'}, [
|
||||||
m('p', m('b', 'Author\'s Note:')),
|
m('p', m('b', 'Author\'s Note:')),
|
||||||
m.trust(notes)]) : null
|
m.trust(notes)]) : null
|
||||||
]
|
]
|
||||||
|
|
||||||
// if author notes are a the beginning of the chapter
|
// if author notes are a the beginning of the chapter
|
||||||
if (notes && chapter.notesFirst) {
|
if (notes && notesFirst) {
|
||||||
sections.reverse()
|
sections.reverse()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,17 +43,18 @@ export function createChapter (ch, chapter, ffc) {
|
||||||
m('head', [
|
m('head', [
|
||||||
m('meta', {charset: 'utf-8'}),
|
m('meta', {charset: 'utf-8'}),
|
||||||
m('link', {rel: 'stylesheet', type: 'text/css', href: '../Styles/style.css'}),
|
m('link', {rel: 'stylesheet', type: 'text/css', href: '../Styles/style.css'}),
|
||||||
m('title', ch.title)
|
m('title', title)
|
||||||
]),
|
]),
|
||||||
m('body', [
|
m('body', [
|
||||||
ffc.options.addChapterHeadings ? m('.chapter-title', [
|
title ? m('.chapter-title', [
|
||||||
m('h1', ch.title),
|
m('h1', title),
|
||||||
m('hr')
|
m('hr')
|
||||||
]) : null,
|
]) : null,
|
||||||
sections,
|
sections,
|
||||||
ffc.options.addCommentsLink ? m('p.double', {style: 'text-align: center; clear: both;'},
|
m('p.double', {style: 'text-align: center; clear: both;'},
|
||||||
m('a.chaptercomments', {href: ch.link + '#comment_list'}, 'Read chapter comments online')
|
link ? m('a.chaptercomments', {href: link + '#comment_list'}, 'Read chapter comments online') : null,
|
||||||
) : null
|
linkNotes ? m('a.chaptercomments', {href: linkNotes}, 'Read author\'s note') : null
|
||||||
|
)
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
))
|
))
|
||||||
|
@ -114,6 +115,23 @@ export function createOpf (ffc) {
|
||||||
remotes.push(m('item', {id: r.filename, href: r.dest, 'media-type': r.type}))
|
remotes.push(m('item', {id: r.filename, href: r.dest, 'media-type': r.type}))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
let manifestChapters = ffc.storyInfo.chapters.map((ch, num) =>
|
||||||
|
m('item', {id: 'chapter_' + zeroFill(3, num + 1), href: 'Text/chapter_' + zeroFill(3, num + 1) + '.xhtml', 'media-type': 'application/xhtml+xml', properties: ch.remote ? 'remote-resources' : null})
|
||||||
|
)
|
||||||
|
let spineChapters = ffc.storyInfo.chapters.map((ch, num) =>
|
||||||
|
m('itemref', {idref: 'chapter_' + zeroFill(3, num + 1)})
|
||||||
|
)
|
||||||
|
let manifestNotes = []
|
||||||
|
let spineNotes = []
|
||||||
|
if (ffc.options.includeAuthorNotes && ffc.options.useAuthorNotesIndex && ffc.hasAuthorNotes) {
|
||||||
|
spineNotes.push(m('itemref', {idref: 'notesnav'}))
|
||||||
|
ffc.chaptersWithNotes.forEach((num) => {
|
||||||
|
let id = 'note_' + zeroFill(3, num + 1)
|
||||||
|
manifestNotes.push(m('item', {id: id, href: 'Text/' + id + '.xhtml', 'media-type': 'application/xhtml+xml'}))
|
||||||
|
spineNotes.push(m('itemref', {idref: id}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let subjects = ffc.subjects
|
let subjects = ffc.subjects
|
||||||
if (ffc.options.joinSubjects) {
|
if (ffc.options.joinSubjects) {
|
||||||
subjects = [subjects.join(', ')]
|
subjects = [subjects.join(', ')]
|
||||||
|
@ -128,7 +146,7 @@ export function createOpf (ffc) {
|
||||||
m('meta', {refines: '#cre', property: 'role', scheme: 'marc:relators'}, 'aut'),
|
m('meta', {refines: '#cre', property: 'role', scheme: 'marc:relators'}, 'aut'),
|
||||||
m('dc:date', new Date((ffc.storyInfo.publishDate || ffc.storyInfo.date_modified) * 1000).toISOString().substring(0, 10)),
|
m('dc:date', new Date((ffc.storyInfo.publishDate || ffc.storyInfo.date_modified) * 1000).toISOString().substring(0, 10)),
|
||||||
m('dc:publisher', 'Fimfiction'),
|
m('dc:publisher', 'Fimfiction'),
|
||||||
m('dc:description', ffc.storyInfo.short_description || ffc.storyInfo.description),
|
m('dc:description', ffc.storyInfo.short_description),
|
||||||
m('dc:source', ffc.storyInfo.url),
|
m('dc:source', ffc.storyInfo.url),
|
||||||
m('dc:language', 'en'),
|
m('dc:language', 'en'),
|
||||||
ffc.coverImage ? m('meta', {name: 'cover', content: 'cover'}) : null,
|
ffc.coverImage ? m('meta', {name: 'cover', content: 'cover'}) : null,
|
||||||
|
@ -141,6 +159,7 @@ export function createOpf (ffc) {
|
||||||
ffc.coverImage ? m('item', {id: 'cover', href: ffc.coverFilename, 'media-type': ffc.coverType, properties: 'cover-image'}) : null,
|
ffc.coverImage ? m('item', {id: 'cover', href: ffc.coverFilename, 'media-type': ffc.coverType, properties: 'cover-image'}) : null,
|
||||||
m('item', {id: 'ncx', href: 'toc.ncx', 'media-type': 'application/x-dtbncx+xml'}),
|
m('item', {id: 'ncx', href: 'toc.ncx', 'media-type': 'application/x-dtbncx+xml'}),
|
||||||
m('item', {id: 'nav', 'href': 'Text/nav.xhtml', 'media-type': 'application/xhtml+xml', properties: 'nav'}),
|
m('item', {id: 'nav', 'href': 'Text/nav.xhtml', 'media-type': 'application/xhtml+xml', properties: 'nav'}),
|
||||||
|
ffc.options.includeAuthorNotes && ffc.options.useAuthorNotesIndex ? m('item', {id: 'notesnav', 'href': 'Text/notesnav.xhtml', 'media-type': 'application/xhtml+xml'}) : null,
|
||||||
|
|
||||||
m('item', {id: 'style', href: 'Styles/style.css', 'media-type': 'text/css'}),
|
m('item', {id: 'style', href: 'Styles/style.css', 'media-type': 'text/css'}),
|
||||||
m('item', {id: 'coverstyle', href: 'Styles/coverstyle.css', 'media-type': 'text/css'}),
|
m('item', {id: 'coverstyle', href: 'Styles/coverstyle.css', 'media-type': 'text/css'}),
|
||||||
|
@ -149,18 +168,16 @@ export function createOpf (ffc) {
|
||||||
m('item', {id: 'coverpage', href: 'Text/cover.xhtml', 'media-type': 'application/xhtml+xml', properties: ffc.coverImage ? 'svg' : undefined}),
|
m('item', {id: 'coverpage', href: 'Text/cover.xhtml', 'media-type': 'application/xhtml+xml', properties: ffc.coverImage ? 'svg' : undefined}),
|
||||||
m('item', {id: 'titlepage', href: 'Text/title.xhtml', 'media-type': 'application/xhtml+xml', properties: ffc.hasRemoteResources.titlePage ? 'remote-resources' : null})
|
m('item', {id: 'titlepage', href: 'Text/title.xhtml', 'media-type': 'application/xhtml+xml', properties: ffc.hasRemoteResources.titlePage ? 'remote-resources' : null})
|
||||||
|
|
||||||
].concat(ffc.storyInfo.chapters.map((ch, num) =>
|
].concat(manifestChapters, manifestNotes, remotes)),
|
||||||
m('item', {id: 'chapter_' + zeroFill(3, num + 1), href: 'Text/chapter_' + zeroFill(3, num + 1) + '.xhtml', 'media-type': 'application/xhtml+xml', properties: ch.remote ? 'remote-resources' : null})
|
|
||||||
), remotes)),
|
|
||||||
|
|
||||||
m('spine', {toc: 'ncx'}, sortSpineItems([
|
m('spine', {toc: 'ncx'}, sortSpineItems([
|
||||||
m('itemref', {idref: 'coverpage'}),
|
m('itemref', {idref: 'coverpage'}),
|
||||||
m('itemref', {idref: 'titlepage'}),
|
m('itemref', {idref: 'titlepage'}),
|
||||||
m('itemref', {idref: 'nav', linear: ffc.storyInfo.chapters.length <= 1 ? 'no' : undefined})
|
m('itemref', {idref: 'nav', linear: ffc.storyInfo.chapters.length <= 1 && !(ffc.options.includeAuthorNotes && ffc.options.useAuthorNotesIndex && ffc.hasAuthorNotes) ? 'no' : undefined})
|
||||||
].concat(ffc.storyInfo.chapters.map((ch, num) =>
|
].concat(
|
||||||
m('itemref', {idref: 'chapter_' + zeroFill(3, num + 1)})
|
spineChapters,
|
||||||
)))),
|
spineNotes
|
||||||
|
))),
|
||||||
m('guide', [
|
m('guide', [
|
||||||
m('reference', {type: 'cover', title: 'Cover', href: 'Text/cover.xhtml'}),
|
m('reference', {type: 'cover', title: 'Cover', href: 'Text/cover.xhtml'}),
|
||||||
m('reference', {type: 'toc', title: 'Contents', href: 'Text/nav.xhtml'})
|
m('reference', {type: 'toc', title: 'Contents', href: 'Text/nav.xhtml'})
|
||||||
|
@ -174,7 +191,7 @@ export function createOpf (ffc) {
|
||||||
function navPoints (list) {
|
function navPoints (list) {
|
||||||
let arr = []
|
let arr = []
|
||||||
for (let i = 0; i < list.length; i++) {
|
for (let i = 0; i < list.length; i++) {
|
||||||
list[i]
|
if (!list[i]) continue
|
||||||
arr.push(m('navPoint', {id: 'navPoint-' + (i + 1), playOrder: i + 1}, [
|
arr.push(m('navPoint', {id: 'navPoint-' + (i + 1), playOrder: i + 1}, [
|
||||||
m('navLabel', m('text', list[i][0])),
|
m('navLabel', m('text', list[i][0])),
|
||||||
m('content', {src: list[i][1]})
|
m('content', {src: list[i][1]})
|
||||||
|
@ -182,7 +199,6 @@ function navPoints (list) {
|
||||||
}
|
}
|
||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createNcx (ffc) {
|
export function createNcx (ffc) {
|
||||||
let tocNcx = '<?xml version="1.0" encoding="utf-8" ?>\n' + pretty.xml(render(
|
let tocNcx = '<?xml version="1.0" encoding="utf-8" ?>\n' + pretty.xml(render(
|
||||||
m('ncx', {version: '2005-1', xmlns: NS.DAISY}, [
|
m('ncx', {version: '2005-1', xmlns: NS.DAISY}, [
|
||||||
|
@ -197,33 +213,50 @@ export function createNcx (ffc) {
|
||||||
['Cover', 'Text/cover.xhtml']
|
['Cover', 'Text/cover.xhtml']
|
||||||
].concat(ffc.storyInfo.chapters.map((ch, num) =>
|
].concat(ffc.storyInfo.chapters.map((ch, num) =>
|
||||||
[ch.title, 'Text/chapter_' + zeroFill(3, num + 1) + '.xhtml']
|
[ch.title, 'Text/chapter_' + zeroFill(3, num + 1) + '.xhtml']
|
||||||
))))
|
), ffc.options.includeAuthorNotes && ffc.options.useAuthorNotesIndex && ffc.hasAuthorNotes ? [['Author\'s Notes', 'Text/notesnav.xhtml']] : null)))
|
||||||
])
|
])
|
||||||
))
|
))
|
||||||
// console.log(tocNcx)
|
// console.log(tocNcx)
|
||||||
return tocNcx
|
return tocNcx
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createNav (ffc) {
|
export function createNav (ffc, mode = 0) {
|
||||||
|
let title, list
|
||||||
|
switch (mode) {
|
||||||
|
case 0:
|
||||||
|
title = 'Contents'
|
||||||
|
list = [m('li', {hidden: ''}, m('a', {href: 'cover.xhtml'}, 'Cover'))]
|
||||||
|
.concat(ffc.storyInfo.chapters.map((ch, num) =>
|
||||||
|
m('li', [
|
||||||
|
m('a.leftalign', {href: 'chapter_' + zeroFill(3, num + 1) + '.xhtml'}, ch.title)
|
||||||
|
// m('span.date', [m('b', ' · '), prettyDate(new Date(ch.date_modified * 1000)), m('span', {style: 'display: none'}, ' · ')]),
|
||||||
|
// m('.floatbox', m('span.wordcount', ch.realWordCount.toLocaleString('en-GB')))
|
||||||
|
])
|
||||||
|
))
|
||||||
|
if (ffc.options.includeAuthorNotes && ffc.options.useAuthorNotesIndex && ffc.hasAuthorNotes) {
|
||||||
|
list.push(m('li', m('a.leftalign', {href: 'notesnav.xhtml'}, 'Author\'s Notes')))
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 1:
|
||||||
|
title = 'Author\'s Notes'
|
||||||
|
list = ffc.chaptersWithNotes.map((num) => {
|
||||||
|
let ch = ffc.storyInfo.chapters[num]
|
||||||
|
return m('li', m('a.leftalign', {href: 'note_' + zeroFill(3, num + 1) + '.xhtml'}, ch.title))
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
let navDocument = '<?xml version="1.0" encoding="utf-8"?>\n<!DOCTYPE html>\n' + pretty.xml(render(
|
let navDocument = '<?xml version="1.0" encoding="utf-8"?>\n<!DOCTYPE html>\n' + pretty.xml(render(
|
||||||
m('html', {xmlns: NS.XHTML, 'xmlns:epub': NS.OPS}, [
|
m('html', {xmlns: NS.XHTML, 'xmlns:epub': NS.OPS}, [
|
||||||
m('head', [
|
m('head', [
|
||||||
m('meta', {charset: 'utf-8'}),
|
m('meta', {charset: 'utf-8'}),
|
||||||
m('link', {rel: 'stylesheet', type: 'text/css', href: '../Styles/style.css'}),
|
m('link', {rel: 'stylesheet', type: 'text/css', href: '../Styles/style.css'}),
|
||||||
m('title', 'Contents')
|
m('title', title)
|
||||||
]),
|
]),
|
||||||
m('body#navpage', [
|
m('body#navpage', [
|
||||||
m('nav#toc', {'epub:type': 'toc'}, [
|
m('nav#toc', mode === 0 ? {'epub:type': 'toc'} : null, [
|
||||||
m('h3', 'Contents'),
|
m('h3', title),
|
||||||
m('ol', [
|
m('ol', list)
|
||||||
m('li', {hidden: ''}, m('a', {href: 'cover.xhtml'}, 'Cover'))
|
|
||||||
].concat(ffc.storyInfo.chapters.map((ch, num) =>
|
|
||||||
m('li', [
|
|
||||||
m('a.leftalign', {href: 'chapter_' + zeroFill(3, num + 1) + '.xhtml'}, ch.title)
|
|
||||||
// m('span.date', [m('b', ' · '), prettyDate(new Date(ch.date_modified * 1000)), m('span', {style: 'display: none'}, ' · ')]),
|
|
||||||
// m('.floatbox', m('span.wordcount', ch.realWordCount.toLocaleString('en-GB')))
|
|
||||||
])
|
|
||||||
)))
|
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
|
Loading…
Reference in a new issue