mirror of
https://github.com/daniel-j/fimfic2epub.git
synced 2024-09-30 00:56:13 +13:00
more settings
This commit is contained in:
parent
4ae5731d14
commit
5710b46593
3 changed files with 102 additions and 56 deletions
|
@ -79,36 +79,17 @@ class FimFic2Epub extends Emitter {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
static parseChapterPage (html) {
|
|
||||||
let trimWhitespace = /^\s*(<br\s*\/?\s*>)+|(<br\s*\/?\s*>)+\s*$/ig
|
|
||||||
|
|
||||||
let authorNotesPos = html.indexOf('<div class="authors-note"')
|
|
||||||
let authorNotes = ''
|
|
||||||
if (authorNotesPos !== -1) {
|
|
||||||
authorNotesPos = authorNotesPos + html.substring(authorNotesPos).indexOf('<b>Author\'s Note:</b>')
|
|
||||||
authorNotes = html.substring(authorNotesPos + 22)
|
|
||||||
authorNotes = authorNotes.substring(0, authorNotes.indexOf('\t\n\t</div>'))
|
|
||||||
authorNotes = authorNotes.trim()
|
|
||||||
authorNotes = authorNotes.replace(trimWhitespace, '')
|
|
||||||
}
|
|
||||||
|
|
||||||
let chapterPos = html.indexOf('<div id="chapter_container">')
|
|
||||||
let chapter = html.substring(chapterPos + 29)
|
|
||||||
|
|
||||||
let pos = chapter.indexOf('\t</div>\t\t\n\t')
|
|
||||||
|
|
||||||
chapter = chapter.substring(0, pos).trim()
|
|
||||||
|
|
||||||
// remove leading and trailing <br /> tags and whitespace
|
|
||||||
chapter = chapter.replace(trimWhitespace, '')
|
|
||||||
return {content: chapter, notes: authorNotes, notesFirst: authorNotesPos < chapterPos}
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor (storyId) {
|
constructor (storyId) {
|
||||||
super()
|
super()
|
||||||
|
|
||||||
this.storyId = FimFic2Epub.getStoryId(storyId)
|
this.storyId = FimFic2Epub.getStoryId(storyId)
|
||||||
|
|
||||||
|
this.options = {
|
||||||
|
addCommentsLink: true,
|
||||||
|
includeAuthorNotes: true,
|
||||||
|
addChapterHeadings: true
|
||||||
|
}
|
||||||
|
|
||||||
this.fetchPromise = null
|
this.fetchPromise = null
|
||||||
|
|
||||||
this.storyInfo = null
|
this.storyInfo = null
|
||||||
|
@ -149,7 +130,6 @@ class FimFic2Epub extends Emitter {
|
||||||
this.storyInfo = storyInfo
|
this.storyInfo = storyInfo
|
||||||
this.storyInfo.uuid = 'urn:fimfiction:' + this.storyInfo.id
|
this.storyInfo.uuid = 'urn:fimfiction:' + this.storyInfo.id
|
||||||
this.filename = FimFic2Epub.getFilename(this.storyInfo)
|
this.filename = FimFic2Epub.getFilename(this.storyInfo)
|
||||||
this.progress(0, 0.3)
|
|
||||||
})
|
})
|
||||||
.then(this.fetchTitlePage.bind(this))
|
.then(this.fetchTitlePage.bind(this))
|
||||||
.then(() => cleanMarkup(this.description)).then((html) => {
|
.then(() => cleanMarkup(this.description)).then((html) => {
|
||||||
|
@ -158,6 +138,15 @@ class FimFic2Epub extends Emitter {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setTitle (title) {
|
||||||
|
this.storyInfo.title = title.trim()
|
||||||
|
this.filename = FimFic2Epub.getFilename(this.storyInfo)
|
||||||
|
}
|
||||||
|
setAuthorName (name) {
|
||||||
|
this.storyInfo.author.name = name.trim()
|
||||||
|
this.filename = FimFic2Epub.getFilename(this.storyInfo)
|
||||||
|
}
|
||||||
|
|
||||||
fetch () {
|
fetch () {
|
||||||
if (this.fetchPromise) {
|
if (this.fetchPromise) {
|
||||||
return this.fetchPromise
|
return this.fetchPromise
|
||||||
|
@ -329,13 +318,11 @@ class FimFic2Epub extends Emitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchTitlePage () {
|
fetchTitlePage () {
|
||||||
this.progress(0, 0.3, 'Fetching title page...')
|
|
||||||
let url = this.storyInfo.url.replace('http://www.fimfiction.net', '')
|
let url = this.storyInfo.url.replace('http://www.fimfiction.net', '')
|
||||||
return fetch(url).then(this.extractTitlePageInfo.bind(this))
|
return fetch(url).then(this.extractTitlePageInfo.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
extractTitlePageInfo (html) {
|
extractTitlePageInfo (html) {
|
||||||
this.progress(0, 0.6)
|
|
||||||
let descPos = html.indexOf('<div class="description" id="description')
|
let descPos = html.indexOf('<div class="description" id="description')
|
||||||
descPos = descPos + html.substring(descPos).indexOf('">') + 2
|
descPos = descPos + html.substring(descPos).indexOf('">') + 2
|
||||||
html = html.substring(descPos)
|
html = html.substring(descPos)
|
||||||
|
@ -405,6 +392,31 @@ class FimFic2Epub extends Emitter {
|
||||||
this.tags = tags
|
this.tags = tags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parseChapterPage (html) {
|
||||||
|
let trimWhitespace = /^\s*(<br\s*\/?\s*>)+|(<br\s*\/?\s*>)+\s*$/ig
|
||||||
|
|
||||||
|
let authorNotesPos = html.indexOf('<div class="authors-note"')
|
||||||
|
let authorNotes = ''
|
||||||
|
if (this.options.includeAuthorNotes && authorNotesPos !== -1) {
|
||||||
|
authorNotesPos = authorNotesPos + html.substring(authorNotesPos).indexOf('<b>Author\'s Note:</b>')
|
||||||
|
authorNotes = html.substring(authorNotesPos + 22)
|
||||||
|
authorNotes = authorNotes.substring(0, authorNotes.indexOf('\t\n\t</div>'))
|
||||||
|
authorNotes = authorNotes.trim()
|
||||||
|
authorNotes = authorNotes.replace(trimWhitespace, '')
|
||||||
|
}
|
||||||
|
|
||||||
|
let chapterPos = html.indexOf('<div id="chapter_container">')
|
||||||
|
let chapter = html.substring(chapterPos + 29)
|
||||||
|
|
||||||
|
let pos = chapter.indexOf('\t</div>\t\t\n\t')
|
||||||
|
|
||||||
|
chapter = chapter.substring(0, pos).trim()
|
||||||
|
|
||||||
|
// remove leading and trailing <br /> tags and whitespace
|
||||||
|
chapter = chapter.replace(trimWhitespace, '')
|
||||||
|
return {content: chapter, notes: authorNotes, notesFirst: authorNotesPos < chapterPos}
|
||||||
|
}
|
||||||
|
|
||||||
fetchChapters () {
|
fetchChapters () {
|
||||||
this.progress(1, 0, 'Fetching chapters...')
|
this.progress(1, 0, 'Fetching chapters...')
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
@ -427,8 +439,8 @@ class FimFic2Epub extends Emitter {
|
||||||
// console.log('Fetching chapter ' + (index + 1) + ' of ' + chapters.length + ': ' + ch.title)
|
// console.log('Fetching chapter ' + (index + 1) + ' of ' + chapters.length + ': ' + ch.title)
|
||||||
let url = ch.link.replace('http://www.fimfiction.net', '')
|
let url = ch.link.replace('http://www.fimfiction.net', '')
|
||||||
fetch(url).then((html) => {
|
fetch(url).then((html) => {
|
||||||
html = FimFic2Epub.parseChapterPage(html)
|
html = this.parseChapterPage(html)
|
||||||
template.createChapter(ch, html).then((html) => {
|
template.createChapter(ch, html, this).then((html) => {
|
||||||
this.findRemoteResources('ch_' + zeroFill(3, index + 1), index, html)
|
this.findRemoteResources('ch_' + zeroFill(3, index + 1), index, html)
|
||||||
this.chapters[index] = html
|
this.chapters[index] = html
|
||||||
completeCount++
|
completeCount++
|
||||||
|
|
60
src/main.js
60
src/main.js
|
@ -56,7 +56,13 @@ let dialog = {
|
||||||
this.coverFile = m.prop(null)
|
this.coverFile = m.prop(null)
|
||||||
this.coverUrl = m.prop('')
|
this.coverUrl = m.prop('')
|
||||||
this.checkboxCoverUrl = m.prop(false)
|
this.checkboxCoverUrl = m.prop(false)
|
||||||
|
|
||||||
|
this.title = m.prop('')
|
||||||
|
this.author = m.prop('')
|
||||||
this.subjects = m.prop(ffc.subjects)
|
this.subjects = m.prop(ffc.subjects)
|
||||||
|
this.addCommentsLink = m.prop(ffc.options.addCommentsLink)
|
||||||
|
this.includeAuthorNotes = m.prop(ffc.options.includeAuthorNotes)
|
||||||
|
this.addChapterHeadings = m.prop(ffc.options.addChapterHeadings)
|
||||||
|
|
||||||
this.setCoverFile = (e) => {
|
this.setCoverFile = (e) => {
|
||||||
this.coverFile(e.target.files ? e.target.files[0] : null)
|
this.coverFile(e.target.files ? e.target.files[0] : null)
|
||||||
|
@ -69,9 +75,7 @@ let dialog = {
|
||||||
let onmove = (e) => {
|
let onmove = (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if (this.dragging()) {
|
if (this.dragging()) {
|
||||||
this.xpos(Math.max(0, e.pageX - offset.x))
|
this.move(e.pageX - offset.x, e.pageY - offset.y)
|
||||||
this.ypos(Math.max(0, e.pageY - offset.y))
|
|
||||||
this.move()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let onup = () => {
|
let onup = () => {
|
||||||
|
@ -89,20 +93,25 @@ let dialog = {
|
||||||
this.isLoading(true)
|
this.isLoading(true)
|
||||||
ffc.fetchMetadata().then(() => {
|
ffc.fetchMetadata().then(() => {
|
||||||
this.isLoading(false)
|
this.isLoading(false)
|
||||||
|
this.title(ffc.storyInfo.title)
|
||||||
|
this.author(ffc.storyInfo.author.name)
|
||||||
m.redraw(true)
|
m.redraw(true)
|
||||||
this.center()
|
this.center()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.move = () => {
|
this.move = (xpos, ypos) => {
|
||||||
|
this.xpos(Math.max(0, xpos))
|
||||||
|
this.ypos(Math.max(0, ypos))
|
||||||
this.el().style.left = this.xpos() + 'px'
|
this.el().style.left = this.xpos() + 'px'
|
||||||
this.el().style.top = this.ypos() + 'px'
|
this.el().style.top = this.ypos() + 'px'
|
||||||
}
|
}
|
||||||
this.center = () => {
|
this.center = () => {
|
||||||
let rect = this.el().firstChild.getBoundingClientRect()
|
let rect = this.el().firstChild.getBoundingClientRect()
|
||||||
this.xpos((window.innerWidth / 2) - (rect.width / 2) + document.body.scrollLeft)
|
this.move(
|
||||||
this.ypos((window.innerHeight / 2) - (rect.height / 2) + document.body.scrollTop)
|
(window.innerWidth / 2) - (rect.width / 2) + document.body.scrollLeft,
|
||||||
this.move()
|
(window.innerHeight / 2) - (rect.height / 2) + document.body.scrollTop
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.createEpub = (e) => {
|
this.createEpub = (e) => {
|
||||||
|
@ -117,6 +126,11 @@ let dialog = {
|
||||||
} else if (this.coverFile()) {
|
} else if (this.coverFile()) {
|
||||||
chain = chain.then(blobToArrayBuffer.bind(null, this.coverFile())).then(ffc.setCoverImage.bind(ffc))
|
chain = chain.then(blobToArrayBuffer.bind(null, this.coverFile())).then(ffc.setCoverImage.bind(ffc))
|
||||||
}
|
}
|
||||||
|
ffc.setTitle(this.title())
|
||||||
|
ffc.setAuthorName(this.author())
|
||||||
|
ffc.options.addCommentsLink = this.addCommentsLink()
|
||||||
|
ffc.options.includeAuthorNotes = this.includeAuthorNotes()
|
||||||
|
ffc.options.addChapterHeadings = this.addChapterHeadings()
|
||||||
m.redraw()
|
m.redraw()
|
||||||
|
|
||||||
chain
|
chain
|
||||||
|
@ -141,15 +155,26 @@ let dialog = {
|
||||||
m('h1', {onmousedown: ctrl.ondown}, m('i.fa.fa-book'), 'Export to EPUB', m('a.close_button', {onclick: closeDialog})),
|
m('h1', {onmousedown: ctrl.ondown}, m('i.fa.fa-book'), 'Export to EPUB', m('a.close_button', {onclick: closeDialog})),
|
||||||
ctrl.isLoading() ? m('div', {style: 'text-align:center;'}, m('i.fa.fa-spin.fa-spinner', {style: 'font-size:50px; margin:20px; color:#777;'})) : m('.drop-down-pop-up-content', [
|
ctrl.isLoading() ? m('div', {style: 'text-align:center;'}, m('i.fa.fa-spin.fa-spinner', {style: 'font-size:50px; margin:20px; color:#777;'})) : m('.drop-down-pop-up-content', [
|
||||||
m('table.properties', [
|
m('table.properties', [
|
||||||
m('tr', m('td.label', 'Custom cover image'), m('td',
|
m('tr', m('td.section_header', {colspan: 3}, m('b', 'General settings'))),
|
||||||
|
m('tr', m('td.label', 'Title'), m('td', {colspan: 2}, m('input', {type: 'text', value: ctrl.title(), onchange: m.withAttr('value', ctrl.title)}))),
|
||||||
|
m('tr', m('td.label', 'Author'), m('td', {colspan: 2}, m('input', {type: 'text', value: ctrl.author(), onchange: m.withAttr('value', ctrl.author)}))),
|
||||||
|
m('tr', m('td.label', 'Custom cover image'),
|
||||||
|
m('td',
|
||||||
ctrl.checkboxCoverUrl() ? m('input', {type: 'url', placeholder: 'Image URL', onchange: m.withAttr('value', ctrl.coverUrl)}) : m('input', {type: 'file', accept: 'image/*', onchange: ctrl.setCoverFile})
|
ctrl.checkboxCoverUrl() ? m('input', {type: 'url', placeholder: 'Image URL', onchange: m.withAttr('value', ctrl.coverUrl)}) : m('input', {type: 'file', accept: 'image/*', onchange: ctrl.setCoverFile})
|
||||||
), m('td', m(checkbox, {checked: ctrl.checkboxCoverUrl(), onchange: m.withAttr('checked', ctrl.checkboxCoverUrl)}, 'Use image URL'))),
|
),
|
||||||
m('tr', m('td.section_header', {colspan: 3}, m('b', 'Metadata'))),
|
m('td', {style: 'width: 1px'}, m(checkbox, {checked: ctrl.checkboxCoverUrl(), onchange: m.withAttr('checked', ctrl.checkboxCoverUrl)}, 'Use image URL'))
|
||||||
|
),
|
||||||
|
m('tr', m('td.label', ''), m('td', {colspan: 2},
|
||||||
|
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 after chapters'),
|
||||||
|
m(checkbox, {checked: ctrl.includeAuthorNotes(), onchange: m.withAttr('checked', ctrl.includeAuthorNotes)}, 'Include author\'s notes')
|
||||||
|
)),
|
||||||
|
|
||||||
|
m('tr', m('td.section_header', {colspan: 3}, m('b', 'Metadata customization'))),
|
||||||
m('tr', m('td.label', 'Categories'), m('td', {colspan: 2},
|
m('tr', m('td.label', 'Categories'), m('td', {colspan: 2},
|
||||||
m('textarea', {rows: 5}, ctrl.subjects().join('\n')),
|
m('textarea', {rows: 5}, ctrl.subjects().join('\n')),
|
||||||
m(checkbox, {checked: false}, 'Join categories into one (for iBooks)')
|
m(checkbox, {checked: false}, 'Join categories into one (iBooks only)')
|
||||||
))
|
))
|
||||||
// m('tr', m('td.label', 'Chapter headings'), m('td', m(checkbox, {checked: true})))
|
|
||||||
]),
|
]),
|
||||||
m('.drop-down-pop-up-footer', [
|
m('.drop-down-pop-up-footer', [
|
||||||
m('button.styled_button', {onclick: ctrl.createEpub, disabled: ffcProgress() >= 0 && ffcProgress() < 1}, 'Create EPUB'),
|
m('button.styled_button', {onclick: ctrl.createEpub, disabled: ffcProgress() >= 0 && ffcProgress() < 1}, 'Create EPUB'),
|
||||||
|
@ -166,23 +191,32 @@ let dialog = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let dialogOpen = false
|
||||||
function openDialog (args, extras) {
|
function openDialog (args, extras) {
|
||||||
|
if (dialogOpen) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dialogOpen = true
|
||||||
m.mount(dialogContainer, m(dialog, args, extras))
|
m.mount(dialogContainer, m(dialog, args, extras))
|
||||||
}
|
}
|
||||||
function closeDialog () {
|
function closeDialog () {
|
||||||
|
dialogOpen = false
|
||||||
m.mount(dialogContainer, null)
|
m.mount(dialogContainer, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
function clickButton () {
|
function clickButton () {
|
||||||
if (!STORY_ID) return
|
if (!STORY_ID) return
|
||||||
if (!ffc) ffc = new FimFic2Epub(STORY_ID)
|
if (!ffc) {
|
||||||
|
ffc = new FimFic2Epub(STORY_ID)
|
||||||
ffc.on('progress', (percent, status) => {
|
ffc.on('progress', (percent, status) => {
|
||||||
|
console.log(Math.round(percent * 100), status)
|
||||||
ffcProgress(percent)
|
ffcProgress(percent)
|
||||||
if (status) {
|
if (status) {
|
||||||
ffcStatus(status)
|
ffcStatus(status)
|
||||||
}
|
}
|
||||||
m.redraw()
|
m.redraw()
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
openDialog()
|
openDialog()
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ 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) {
|
export function createChapter (ch, chapter, ffc) {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
cleanMarkup(chapter.content),
|
cleanMarkup(chapter.content),
|
||||||
cleanMarkup(chapter.notes)
|
cleanMarkup(chapter.notes)
|
||||||
|
@ -53,14 +53,14 @@ export function createChapter (ch, chapter) {
|
||||||
m('title', ch.title)
|
m('title', ch.title)
|
||||||
]),
|
]),
|
||||||
m('body', [
|
m('body', [
|
||||||
m('.chapter-title', [
|
ffc.options.addChapterHeadings ? m('.chapter-title', [
|
||||||
m('h1', ch.title),
|
m('h1', ch.title),
|
||||||
m('hr')
|
m('hr')
|
||||||
]),
|
]) : null,
|
||||||
content,
|
content,
|
||||||
m('p.double', {style: 'text-align: center; clear: both;'},
|
ffc.options.addCommentsLink ? m('p.double', {style: 'text-align: center; clear: both;'},
|
||||||
m('a.chaptercomments', {href: ch.link + '#comment_list'}, 'Read chapter comments online')
|
m('a.chaptercomments', {href: ch.link + '#comment_list'}, 'Read chapter comments online')
|
||||||
)
|
) : null
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
))
|
))
|
||||||
|
|
Loading…
Reference in a new issue