mirror of
https://github.com/daniel-j/fimfic2epub.git
synced 2024-05-07 05:52:48 +12:00
lint
This commit is contained in:
parent
19194dea31
commit
9a2e60c1c9
|
@ -33,7 +33,7 @@ if (isStandalone) {
|
|||
webpackConfig.pop()
|
||||
}
|
||||
|
||||
let watchOpts = {
|
||||
const watchOpts = {
|
||||
readDelay: 500,
|
||||
verbose: true,
|
||||
read: false
|
||||
|
@ -41,12 +41,12 @@ let watchOpts = {
|
|||
|
||||
let packageVersion = require('./package.json').version
|
||||
|
||||
let webpackDefines = new webpack.DefinePlugin({
|
||||
const webpackDefines = new webpack.DefinePlugin({
|
||||
FIMFIC2EPUB_VERSION: JSON.stringify(packageVersion)
|
||||
})
|
||||
|
||||
// No need to bloat the build with a list of all tlds...
|
||||
let replaceTlds = new webpack.NormalModuleReplacementPlugin(/^tlds$/, '../../src/false')
|
||||
const replaceTlds = new webpack.NormalModuleReplacementPlugin(/^tlds$/, '../../src/false')
|
||||
|
||||
webpackConfig.forEach((c) => {
|
||||
c.plugins.push(webpackDefines)
|
||||
|
@ -89,8 +89,8 @@ function webpackTask () {
|
|||
}
|
||||
|
||||
function convertFontAwesomeVars (contents) {
|
||||
let vars = {}
|
||||
let matchVar = /\$fa-var-(.*?): "\\(.*?)";/g
|
||||
const vars = {}
|
||||
const matchVar = /\$fa-var-(.*?): "\\(.*?)";/g
|
||||
let ma
|
||||
for (;(ma = matchVar.exec(contents));) {
|
||||
vars[ma[1]] = String.fromCharCode(parseInt(ma[2], 16))
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"url": "https://github.com/daniel-j/fimfic2epub.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "NODE_ENV=production gulp",
|
||||
"build": "gulp",
|
||||
"dev": "NODE_ENV=development gulp"
|
||||
},
|
||||
"bin": {
|
||||
|
|
|
@ -31,9 +31,9 @@ const trimWhitespace = /^\s*(<br\s*\/?\s*>)+|(<br\s*\/?\s*>)+\s*$/ig
|
|||
class FimFic2Epub extends EventEmitter {
|
||||
static getStoryId (id) {
|
||||
if (isNaN(id)) {
|
||||
let url = URL(id)
|
||||
const url = URL(id)
|
||||
if (url.hostname === 'www.fimfiction.net' || url.hostname === 'fimfiction.net') {
|
||||
let m = url.pathname.match(/^\/story\/(\d+)/)
|
||||
const m = url.pathname.match(/^\/story\/(\d+)/)
|
||||
if (m) {
|
||||
id = m[1]
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ class FimFic2Epub extends EventEmitter {
|
|||
static fetchStoryInfo (storyId, raw = false) {
|
||||
return new Promise((resolve, reject) => {
|
||||
storyId = FimFic2Epub.getStoryId(storyId)
|
||||
let url = '/api/story.php?story=' + storyId
|
||||
const url = '/api/story.php?story=' + storyId
|
||||
fetch(url).then((content) => {
|
||||
let data
|
||||
try {
|
||||
|
@ -63,7 +63,7 @@ class FimFic2Epub extends EventEmitter {
|
|||
reject(new Error(data.error + ' (id: ' + storyId + ')'))
|
||||
return
|
||||
}
|
||||
let story = data.story
|
||||
const story = data.story
|
||||
if (raw) {
|
||||
resolve(story)
|
||||
return
|
||||
|
@ -223,20 +223,20 @@ class FimFic2Epub extends EventEmitter {
|
|||
|
||||
this.progress(0, 0, 'Fetching chapters...')
|
||||
|
||||
let chapterCount = this.storyInfo.chapters.length
|
||||
let url = 'https://fimfiction.net/story/download/' + this.storyInfo.id + '/html'
|
||||
const chapterCount = this.storyInfo.chapters.length
|
||||
const url = 'https://fimfiction.net/story/download/' + this.storyInfo.id + '/html'
|
||||
|
||||
this.pcache.chapters = fetch(url).then((html) => {
|
||||
let p = Promise.resolve()
|
||||
let matchChapter = /<article class="chapter">[\s\S]*?<\/header>([\s\S]*?)<\/article>/g
|
||||
const matchChapter = /<article class="chapter">[\s\S]*?<\/header>([\s\S]*?)<\/article>/g
|
||||
for (let ma, i = 0; (ma = matchChapter.exec(html)); i++) {
|
||||
const ch = this.storyInfo.chapters[i]
|
||||
let chapterContent = ma[1]
|
||||
chapterContent = chapterContent.replace(/<footer>[\s\S]*?<\/footer>/g, '').trim()
|
||||
|
||||
let authorNotesPos = chapterContent.indexOf('<aside ')
|
||||
const authorNotesPos = chapterContent.indexOf('<aside ')
|
||||
let notesContent = ''
|
||||
let notesFirst = authorNotesPos === 0
|
||||
const notesFirst = authorNotesPos === 0
|
||||
if (authorNotesPos !== -1) {
|
||||
chapterContent = chapterContent.replace(/<aside class="authors-note">([\s\S]*?)<\/aside>/, (match, content, pos) => {
|
||||
content = content.replace(/<header><h1>.*?<\/h1><\/header>/, '')
|
||||
|
@ -290,14 +290,14 @@ class FimFic2Epub extends EventEmitter {
|
|||
return Promise.resolve()
|
||||
}
|
||||
|
||||
let checksums = new Map()
|
||||
const checksums = new Map()
|
||||
|
||||
this.progress(0, 0, 'Fetching remote files...')
|
||||
this.pcache.remoteResources = new Promise((resolve, reject) => {
|
||||
let iter = this.remoteResources.entries()
|
||||
const iter = this.remoteResources.entries()
|
||||
let completeCount = 0
|
||||
|
||||
let next = (r) => {
|
||||
const next = (r) => {
|
||||
completeCount++
|
||||
if (r.data) {
|
||||
this.progress(0, completeCount / this.remoteResources.size, 'Fetched remote file ' + completeCount + ' / ' + this.remoteResources.size)
|
||||
|
@ -307,7 +307,7 @@ class FimFic2Epub extends EventEmitter {
|
|||
recursive()
|
||||
}
|
||||
|
||||
let recursive = () => {
|
||||
const recursive = () => {
|
||||
let r = iter.next().value
|
||||
if (!r) {
|
||||
if (completeCount === this.remoteResources.size) {
|
||||
|
@ -315,7 +315,7 @@ class FimFic2Epub extends EventEmitter {
|
|||
}
|
||||
return
|
||||
}
|
||||
let url = r[0]
|
||||
const url = r[0]
|
||||
r = r[1]
|
||||
if (r.data) {
|
||||
next(r)
|
||||
|
@ -335,9 +335,9 @@ class FimFic2Epub extends EventEmitter {
|
|||
}
|
||||
}
|
||||
if (info) {
|
||||
let checksum = crc32(isNode ? data : new Uint8Array(data))
|
||||
const checksum = crc32(isNode ? data : new Uint8Array(data))
|
||||
if (checksums.has(checksum)) {
|
||||
let sameFile = this.remoteResources.get(checksums.get(checksum))
|
||||
const sameFile = this.remoteResources.get(checksums.get(checksum))
|
||||
r.dest = sameFile.dest
|
||||
r.filename = sameFile.dest
|
||||
r.type = sameFile.type
|
||||
|
@ -348,11 +348,11 @@ class FimFic2Epub extends EventEmitter {
|
|||
data = await utils.webp2png(isNode ? data : new Uint8Array(data))
|
||||
info = fileType(data)
|
||||
}
|
||||
let type = info.mime
|
||||
const type = info.mime
|
||||
r.type = type
|
||||
let isImage = type.startsWith('image/')
|
||||
let folder = isImage ? 'Images' : 'Misc'
|
||||
let dest = folder + '/*.' + info.ext
|
||||
const isImage = type.startsWith('image/')
|
||||
const folder = isImage ? 'Images' : 'Misc'
|
||||
const dest = folder + '/*.' + info.ext
|
||||
r.dest = dest.replace('*', r.filename)
|
||||
r.data = data
|
||||
}
|
||||
|
@ -393,8 +393,8 @@ class FimFic2Epub extends EventEmitter {
|
|||
this.notesHtml.length = 0
|
||||
|
||||
for (let i = 0; i < this.chapters.length; i++) {
|
||||
let ch = this.storyInfo.chapters[i]
|
||||
let chapter = this.chapters[i]
|
||||
const ch = this.storyInfo.chapters[i]
|
||||
const chapter = this.chapters[i]
|
||||
let content = chapter.content
|
||||
|
||||
if (this.options.typogrify) {
|
||||
|
@ -486,8 +486,8 @@ class FimFic2Epub extends EventEmitter {
|
|||
this.zip.file('OEBPS/Styles/navstyle.css', Buffer.from(navstyleCss, 'utf8'))
|
||||
|
||||
for (let i = 0; i < this.chapters.length; i++) {
|
||||
let filename = 'OEBPS/Text/chapter_' + zeroFill(3, i + 1) + '.xhtml'
|
||||
let html = this.chaptersHtml[i]
|
||||
const filename = 'OEBPS/Text/chapter_' + zeroFill(3, i + 1) + '.xhtml'
|
||||
const html = this.chaptersHtml[i]
|
||||
this.zip.file(filename, Buffer.from(html, 'utf8'))
|
||||
}
|
||||
|
||||
|
@ -496,8 +496,8 @@ class FimFic2Epub extends EventEmitter {
|
|||
|
||||
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]
|
||||
const filename = 'OEBPS/Text/note_' + zeroFill(3, i + 1) + '.xhtml'
|
||||
const html = this.notesHtml[i]
|
||||
this.zip.file(filename, Buffer.from(html, 'utf8'))
|
||||
}
|
||||
}
|
||||
|
@ -511,7 +511,7 @@ class FimFic2Epub extends EventEmitter {
|
|||
(paragraphsCss[this.options.paragraphStyle] || '')
|
||||
, 'utf8'))
|
||||
|
||||
let remoteDestCache = new Set()
|
||||
const remoteDestCache = new Set()
|
||||
this.remoteResources.forEach((r) => {
|
||||
if (r.dest && !remoteDestCache.has(r.dest)) {
|
||||
this.zip.file('OEBPS/' + r.dest, r.data)
|
||||
|
@ -541,7 +541,7 @@ class FimFic2Epub extends EventEmitter {
|
|||
compression: 'DEFLATE',
|
||||
compressionOptions: { level: 9 }
|
||||
}, (metadata) => { // onUpdate
|
||||
let currentPercent = Math.round(metadata.percent / 10) * 10
|
||||
const currentPercent = Math.round(metadata.percent / 10) * 10
|
||||
if (lastPercent !== currentPercent) {
|
||||
lastPercent = currentPercent
|
||||
this.progress(0, currentPercent / 100, 'Compressing...')
|
||||
|
@ -575,7 +575,7 @@ class FimFic2Epub extends EventEmitter {
|
|||
compressionOptions: { level: 9 }
|
||||
}, (metadata) => {
|
||||
if (onUpdate) onUpdate(metadata)
|
||||
let currentPercent = Math.round(metadata.percent / 20) * 20
|
||||
const currentPercent = Math.round(metadata.percent / 20) * 20
|
||||
if (lastPercent !== currentPercent) {
|
||||
lastPercent = currentPercent
|
||||
this.progress(0, currentPercent / 100, 'Compressing...')
|
||||
|
@ -587,13 +587,15 @@ class FimFic2Epub extends EventEmitter {
|
|||
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)
|
||||
}
|
||||
|
||||
setCoverImage (buffer) {
|
||||
buffer = isNode ? buffer : Buffer.from(new Uint8Array(buffer))
|
||||
let info = fileType(buffer)
|
||||
const info = fileType(buffer)
|
||||
if (!info || !info.mime.startsWith('image/')) {
|
||||
throw new Error('Invalid image')
|
||||
}
|
||||
|
@ -620,21 +622,21 @@ class FimFic2Epub extends EventEmitter {
|
|||
|
||||
findRemoteResources (prefix, where, html) {
|
||||
let remoteCounter = 1
|
||||
let matchUrl = /<img.*?src="([^">]*\/([^">]*?))".*?>/g
|
||||
let emoticonUrl = /static\.fimfiction\.net\/images\/emoticons\/([a-z_]*)\.[a-z]*$/
|
||||
const matchUrl = /<img.*?src="([^">]*\/([^">]*?))".*?>/g
|
||||
const emoticonUrl = /static\.fimfiction\.net\/images\/emoticons\/([a-z_]*)\.[a-z]*$/
|
||||
|
||||
for (let ma; (ma = matchUrl.exec(html));) {
|
||||
let url = ma[1]
|
||||
let cleanurl = entities.decode(url)
|
||||
const url = ma[1]
|
||||
const cleanurl = entities.decode(url)
|
||||
if (this.remoteResources.has(cleanurl)) {
|
||||
let r = this.remoteResources.get(cleanurl)
|
||||
const r = this.remoteResources.get(cleanurl)
|
||||
if (r.where.indexOf(where) === -1) {
|
||||
r.where.push(where)
|
||||
}
|
||||
continue
|
||||
}
|
||||
let filename = prefix + '_' + remoteCounter
|
||||
let emoticon = url.match(emoticonUrl)
|
||||
const emoticon = url.match(emoticonUrl)
|
||||
if (emoticon) {
|
||||
filename = 'emoticon_' + emoticon[1]
|
||||
}
|
||||
|
@ -644,7 +646,7 @@ class FimFic2Epub extends EventEmitter {
|
|||
}
|
||||
|
||||
async findIcons () {
|
||||
let matchIcon = /<i class="fa fa-fw fa-(.*?)"/g
|
||||
const matchIcon = /<i class="fa fa-fw fa-(.*?)"/g
|
||||
this.usedIcons.clear()
|
||||
|
||||
const scan = (html) => {
|
||||
|
@ -667,10 +669,10 @@ class FimFic2Epub extends EventEmitter {
|
|||
return
|
||||
}
|
||||
|
||||
let glyphs = [...this.usedIcons].map((name) => {
|
||||
const glyphs = [...this.usedIcons].map((name) => {
|
||||
return fontAwesomeCodes[name].charCodeAt(0)
|
||||
})
|
||||
let fontFile = require('font-awesome/fonts/fontawesome-webfont.ttf')
|
||||
const fontFile = require('font-awesome/fonts/fontawesome-webfont.ttf')
|
||||
this.iconsFont = await subsetFont(fontFile, glyphs, { local: isNode })
|
||||
}
|
||||
|
||||
|
@ -692,7 +694,7 @@ class FimFic2Epub extends EventEmitter {
|
|||
return Promise.resolve(this.coverImage)
|
||||
}
|
||||
this.coverImage = null
|
||||
let url = this.coverUrl || this.storyInfo.full_image
|
||||
const url = this.coverUrl || this.storyInfo.full_image
|
||||
if (!url) {
|
||||
console.warn('Story has no image. Generating one...')
|
||||
let canvas
|
||||
|
@ -703,7 +705,7 @@ class FimFic2Epub extends EventEmitter {
|
|||
canvas.width = 1080
|
||||
canvas.height = 1440
|
||||
}
|
||||
let ctx = canvas.getContext('2d')
|
||||
const ctx = canvas.getContext('2d')
|
||||
ctx.fillStyle = 'white'
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height)
|
||||
|
||||
|
@ -714,8 +716,8 @@ class FimFic2Epub extends EventEmitter {
|
|||
ctx.strokeRect(20, 20, canvas.width - 40, canvas.height - 40)
|
||||
ctx.strokeRect(12, 12, canvas.width - 24, canvas.height - 24)
|
||||
|
||||
let title = this.storyInfo.title
|
||||
let author = this.storyInfo.author.name
|
||||
const title = this.storyInfo.title
|
||||
const author = this.storyInfo.author.name
|
||||
|
||||
let fontSize = 150
|
||||
let width
|
||||
|
@ -744,14 +746,14 @@ class FimFic2Epub extends EventEmitter {
|
|||
|
||||
this.pcache.coverImage = fetchRemote(url, 'arraybuffer').then((data) => {
|
||||
data = isNode ? data : new Uint8Array(data)
|
||||
let info = fileType(data)
|
||||
const info = fileType(data)
|
||||
if (info) {
|
||||
let type = info.mime
|
||||
let isImage = type.startsWith('image/')
|
||||
const type = info.mime
|
||||
const isImage = type.startsWith('image/')
|
||||
if (!isImage) {
|
||||
return null
|
||||
}
|
||||
let filename = 'Images/cover.' + info.ext
|
||||
const filename = 'Images/cover.' + info.ext
|
||||
this.coverFilename = filename
|
||||
this.coverType = type
|
||||
|
||||
|
@ -771,7 +773,7 @@ class FimFic2Epub extends EventEmitter {
|
|||
|
||||
fetchTitlePage () {
|
||||
let viewMature = true
|
||||
let isStoryMature = this.storyInfo.content_rating === 2
|
||||
const isStoryMature = this.storyInfo.content_rating === 2
|
||||
if (!isNode) {
|
||||
viewMature = document.cookie.split('; ').includes('view_mature=true')
|
||||
if (!viewMature && isStoryMature) {
|
||||
|
@ -796,19 +798,19 @@ class FimFic2Epub extends EventEmitter {
|
|||
startTagsPos += html.substring(startTagsPos).indexOf('<ul class="story-tags">') + 23
|
||||
let tagsHtml = html.substring(startTagsPos)
|
||||
|
||||
let endTagsPos = tagsHtml.indexOf('</ul>')
|
||||
const endTagsPos = tagsHtml.indexOf('</ul>')
|
||||
tagsHtml = tagsHtml.substring(0, endTagsPos)
|
||||
|
||||
let tags = []
|
||||
const tags = []
|
||||
let c
|
||||
tags.byImage = {}
|
||||
this.subjects.length = 0
|
||||
this.subjects.push('Fimfiction')
|
||||
this.subjects.push(this.storyInfo.content_rating_text)
|
||||
|
||||
let matchTag = /<a href="([^"]*?)" class="([^"]*?)" title="[^"]*?" data-tag="([^"]*?)".*?>(.*?)<\/a>/g
|
||||
const matchTag = /<a href="([^"]*?)" class="([^"]*?)" title="[^"]*?" data-tag="([^"]*?)".*?>(.*?)<\/a>/g
|
||||
for (;(c = matchTag.exec(tagsHtml));) {
|
||||
let cat = {
|
||||
const cat = {
|
||||
url: 'https://fimfiction.net' + c[1],
|
||||
className: 'story-tag ' + c[2],
|
||||
name: entities.decode(c[4]),
|
||||
|
@ -831,12 +833,12 @@ class FimFic2Epub extends EventEmitter {
|
|||
html = html.substring(html.indexOf('<hr />') + 6)
|
||||
}
|
||||
|
||||
let endDescPos = html.indexOf('</span>\n')
|
||||
let description = html.substring(0, endDescPos).trim()
|
||||
const endDescPos = html.indexOf('</span>\n')
|
||||
const description = html.substring(0, endDescPos).trim()
|
||||
this.description = description
|
||||
|
||||
html = html.substring(endDescPos + 7)
|
||||
let extraPos = html.indexOf('<div class="extra_story_data">')
|
||||
const extraPos = html.indexOf('<div class="extra_story_data">')
|
||||
html = html.substring(extraPos + 30)
|
||||
|
||||
ma = html.match(/<span class="approved-date">.*?data-time="(.*?)".*?<\/span>/)
|
||||
|
@ -848,7 +850,7 @@ class FimFic2Epub extends EventEmitter {
|
|||
}
|
||||
|
||||
parseChapterPage (html) {
|
||||
let trimWhitespace = /^\s*(<br\s*\/?\s*>)+|(<br\s*\/?\s*>)+\s*$/ig
|
||||
const trimWhitespace = /^\s*(<br\s*\/?\s*>)+|(<br\s*\/?\s*>)+\s*$/ig
|
||||
|
||||
let authorNotesPos = html.indexOf('<div class="authors-note"')
|
||||
let authorNotes = ''
|
||||
|
@ -860,10 +862,10 @@ class FimFic2Epub extends EventEmitter {
|
|||
authorNotes = authorNotes.replace(trimWhitespace, '')
|
||||
}
|
||||
|
||||
let chapterPos = html.indexOf('<div class="bbcode">')
|
||||
const chapterPos = html.indexOf('<div class="bbcode">')
|
||||
let chapter = html.substring(chapterPos + 20)
|
||||
|
||||
let pos = chapter.indexOf('\t\t</div>\n\t</div>\t\t\n\t\t\t\t\t</div>\n')
|
||||
const pos = chapter.indexOf('\t\t</div>\n\t</div>\t\t\n\t\t\t\t\t</div>\n')
|
||||
|
||||
chapter = chapter.substring(0, pos).trim()
|
||||
|
||||
|
@ -877,9 +879,9 @@ class FimFic2Epub extends EventEmitter {
|
|||
if (!this.options.includeExternal) {
|
||||
this.remoteResources.forEach((r, url) => {
|
||||
if (r.originalUrl && r.where) {
|
||||
let ourl = new RegExp(escapeStringRegexp(r.originalUrl), 'g')
|
||||
const ourl = new RegExp(escapeStringRegexp(r.originalUrl), 'g')
|
||||
for (var i = 0; i < r.where.length; i++) {
|
||||
let w = r.where[i]
|
||||
const w = r.where[i]
|
||||
if (typeof w === 'number') {
|
||||
if (ourl.test(this.chapters[w])) {
|
||||
this.storyInfo.chapters[w].remote = true
|
||||
|
@ -895,10 +897,10 @@ class FimFic2Epub extends EventEmitter {
|
|||
} else {
|
||||
this.remoteResources.forEach((r, url) => {
|
||||
if (r.dest && r.originalUrl && r.where) {
|
||||
let dest = '../' + r.dest
|
||||
let ourl = new RegExp(escapeStringRegexp(r.originalUrl), 'g')
|
||||
const dest = '../' + r.dest
|
||||
const ourl = new RegExp(escapeStringRegexp(r.originalUrl), 'g')
|
||||
for (var i = 0; i < r.where.length; i++) {
|
||||
let w = r.where[i]
|
||||
const w = r.where[i]
|
||||
if (typeof w === 'object' && w.chapter !== undefined && this.chaptersHtml[w.chapter]) {
|
||||
this.chaptersHtml[w.chapter] = this.chaptersHtml[w.chapter].replace(ourl, dest)
|
||||
} else if (typeof w === 'object' && w.note !== undefined && this.notesHtml[w.note]) {
|
||||
|
|
|
@ -44,12 +44,12 @@ export async function cleanMarkup (html) {
|
|||
html = html.replace('<blockquote style="margin: 10px 0px; box-sizing:border-box; -moz-box-sizing:border-box;margin-left:25px; padding: 15px;background-color: #F7F7F7;border: 1px solid #AAA;width: 50%;float:right;box-shadow: 5px 5px 0px #EEE;">', '<blockquote class="right_insert">')
|
||||
|
||||
// add alt attributes to images that don't have them
|
||||
let imageEmbed = /<img src="(.*?)" \/>/g
|
||||
const imageEmbed = /<img src="(.*?)" \/>/g
|
||||
html = await replaceAsync(html, imageEmbed, (match, src) => render(m('img', { src: entities.decode(src), alt: 'Image' }), { strict: true }))
|
||||
|
||||
// Fix links pointing to pages on fimfiction
|
||||
// Example: <a href="/user/djazz" rel="nofollow">djazz</a>
|
||||
let matchLink = /(<a .?href=")(.+?)(".+?>)/g
|
||||
const matchLink = /(<a .?href=")(.+?)(".+?>)/g
|
||||
html = html.replace(matchLink, (match, head, url, tail) => {
|
||||
if (url.substring(0, 1) !== '#' && url.substring(0, 2) !== '//' && url.substring(0, 4) !== 'http' && url.substring(0, 1) === '/') {
|
||||
url = 'https://fimfiction.net' + url
|
||||
|
@ -62,14 +62,14 @@ export async function cleanMarkup (html) {
|
|||
const query = new Map()
|
||||
let completeCount = 0
|
||||
|
||||
let matchYouTube = /<p><a class="embed" href="https:\/\/www\.youtube\.com\/watch\?v=(.*?)">.*?<\/a><\/p>/g
|
||||
const matchYouTube = /<p><a class="embed" href="https:\/\/www\.youtube\.com\/watch\?v=(.*?)">.*?<\/a><\/p>/g
|
||||
for (let ma; (ma = matchYouTube.exec(html));) {
|
||||
let youtubeId = ma[1].match(/^[^&]+/)[0]
|
||||
const youtubeId = ma[1].match(/^[^&]+/)[0]
|
||||
cache.set(youtubeId, null)
|
||||
query.set(entities.decode(ma[1]), youtubeId)
|
||||
}
|
||||
|
||||
let matchSoundCloud = /<p><a class="embed" href="(https:\/\/soundcloud\.com\/.*?)">.*?<\/a><\/p>/g
|
||||
const matchSoundCloud = /<p><a class="embed" href="(https:\/\/soundcloud\.com\/.*?)">.*?<\/a><\/p>/g
|
||||
html = await replaceAsync(html, matchSoundCloud, (match, url) => {
|
||||
return render(m('.soundcloud.leftalign', [
|
||||
'SoundCloud: ', m('a', { href: entities.decode(url), rel: 'nofollow' }, url.replace('https://soundcloud.com/', '').replace(/[-_]/g, ' ').replace('/', ' - ').replace(/ {2}/g, ' '))
|
||||
|
@ -104,12 +104,12 @@ export async function cleanMarkup (html) {
|
|||
|
||||
function replaceYouTube (match, queryString) {
|
||||
queryString = entities.decode(queryString)
|
||||
let youtubeId = query.get(queryString)
|
||||
const youtubeId = query.get(queryString)
|
||||
let thumbnail = 'https://img.youtube.com/vi/' + youtubeId + '/hqdefault.jpg'
|
||||
let youtubeUrl = 'https://youtube.com/watch?v=' + queryString
|
||||
const youtubeUrl = 'https://youtube.com/watch?v=' + queryString
|
||||
let title = 'Youtube Video'
|
||||
let caption = ''
|
||||
let data = cache.get(youtubeId)
|
||||
const data = cache.get(youtubeId)
|
||||
|
||||
if (data) {
|
||||
thumbnail = (data.thumbnails.standard || data.thumbnails.high || data.thumbnails.medium || data.thumbnails.default).url
|
||||
|
@ -138,7 +138,7 @@ export function fixDoubleSpacing (html) {
|
|||
|
||||
export function fixParagraphIndent (html) {
|
||||
// from FimFictionConverter by Nyerguds
|
||||
let fixIndent = 2
|
||||
const fixIndent = 2
|
||||
if (fixIndent > 0) {
|
||||
// only trigger indenting when finding as many whitespace characters in a row as indicated by the FixIndent setting.
|
||||
|
||||
|
|
|
@ -39,7 +39,6 @@ if (outputStdout) {
|
|||
const mock = require('mithril/test-utils/browserMock')(global)
|
||||
global.requestAnimationFrame = mock.requestAnimationFrame
|
||||
|
||||
|
||||
const htmlToText = require('./utils').htmlToText
|
||||
const FimFic2Epub = require('./FimFic2Epub').default
|
||||
const fs = require('fs')
|
||||
|
|
|
@ -10,13 +10,13 @@ export const NS = {
|
|||
}
|
||||
|
||||
export const tidyOptions = {
|
||||
'indent': 'auto',
|
||||
indent: 'auto',
|
||||
'numeric-entities': 'yes',
|
||||
'output-xhtml': 'yes',
|
||||
'alt-text': 'Image',
|
||||
'wrap': '0',
|
||||
'quiet': 'yes',
|
||||
'newline': 'LF',
|
||||
wrap: '0',
|
||||
quiet: 'yes',
|
||||
newline: 'LF',
|
||||
'tidy-mark': 'no',
|
||||
'show-body-only': 'auto'
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import fetch from './fetch'
|
|||
|
||||
if (typeof safari !== 'undefined') {
|
||||
safari.application.addEventListener('message', function (ev) {
|
||||
let url = ev.message
|
||||
const url = ev.message
|
||||
fetch(url, 'arraybuffer').then((buffer) => {
|
||||
console.log('Fetched ' + url)
|
||||
ev.target.page.dispatchMessage('remote', {
|
||||
|
@ -14,12 +14,12 @@ if (typeof safari !== 'undefined') {
|
|||
})
|
||||
}, false)
|
||||
} else {
|
||||
let onMessage = chrome.extension.onMessage ? chrome.extension.onMessage : chrome.runtime.onMessage
|
||||
const onMessage = chrome.extension.onMessage ? chrome.extension.onMessage : chrome.runtime.onMessage
|
||||
|
||||
onMessage.addListener(function (request, sender, sendResponse) {
|
||||
if (typeof request === 'string') {
|
||||
fetch(request, 'blob').then((blob) => {
|
||||
let ourl = URL.createObjectURL(blob)
|
||||
const ourl = URL.createObjectURL(blob)
|
||||
console.log('Fetched', request)
|
||||
sendResponse(ourl)
|
||||
})
|
||||
|
|
10
src/fetch.js
10
src/fetch.js
|
@ -11,9 +11,9 @@ function fetchNode (url, responseType) {
|
|||
url: url,
|
||||
encoding: responseType ? null : 'utf8',
|
||||
headers: {
|
||||
'referer': 'https://fimfiction.net/',
|
||||
'cookie': 'view_mature=true',
|
||||
'accept': '*/*'
|
||||
referer: 'https://fimfiction.net/',
|
||||
cookie: 'view_mature=true',
|
||||
accept: '*/*'
|
||||
}
|
||||
}, (error, response, body) => {
|
||||
if (error) {
|
||||
|
@ -46,7 +46,7 @@ export default function fetch (url, responseType) {
|
|||
cache: 'default',
|
||||
redirect: 'follow',
|
||||
headers: {
|
||||
'accept': '*/*' // Fix for not getting webp images from Fimfiction
|
||||
accept: '*/*' // Fix for not getting webp images from Fimfiction
|
||||
},
|
||||
referrer: window.location.origin
|
||||
}).then((response) => {
|
||||
|
@ -61,7 +61,7 @@ export default function fetch (url, responseType) {
|
|||
reject(new Error('Error fetching ' + url + ' (' + err + ')'))
|
||||
})
|
||||
} else {
|
||||
let x = new XMLHttpRequest()
|
||||
const x = new XMLHttpRequest()
|
||||
x.withCredentials = true
|
||||
x.setRequestHeader('accept', '*/*') // Fix for not getting webp images from Fimfiction
|
||||
x.open('get', url, true)
|
||||
|
|
|
@ -7,25 +7,25 @@ const safariQueue = {}
|
|||
|
||||
// messaging with the safari extension global page
|
||||
function safariHandler (ev) {
|
||||
let type = ev.message.type
|
||||
let url = ev.message.input
|
||||
let data = ev.message.output // arraybuffer
|
||||
const type = ev.message.type
|
||||
const url = ev.message.input
|
||||
const data = ev.message.output // arraybuffer
|
||||
if (!safariQueue[url]) {
|
||||
// console.error("Unable to get callback for " + url, JSON.stringify(safariQueue))
|
||||
return
|
||||
}
|
||||
let cb = safariQueue[url].cb
|
||||
let responseType = safariQueue[url].responseType
|
||||
const cb = safariQueue[url].cb
|
||||
const responseType = safariQueue[url].responseType
|
||||
console.log(url, cb, responseType, data)
|
||||
delete safariQueue[url]
|
||||
|
||||
if (responseType === 'blob') {
|
||||
let blob = new Blob([data], { type: type })
|
||||
const blob = new Blob([data], { type: type })
|
||||
cb(blob, type)
|
||||
} else {
|
||||
if (!responseType) {
|
||||
let blob = new Blob([data], { type: type })
|
||||
let fr = new FileReader()
|
||||
const blob = new Blob([data], { type: type })
|
||||
const fr = new FileReader()
|
||||
fr.onloadend = function () {
|
||||
cb(fr.result, type)
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ function textToSentences (text) {
|
|||
.split(/\s*\0/)
|
||||
|
||||
for (let i = 0; i < tokenSentences.length; i++) {
|
||||
let s = tokenSentences[i]
|
||||
const s = tokenSentences[i]
|
||||
if (s.trim().length === 0) {
|
||||
if (i - 1 >= 0) tokenSentences[i - 1] += s
|
||||
tokenSentences.splice(i, 1)
|
||||
|
@ -61,15 +61,15 @@ function textToSentences (text) {
|
|||
function fixupTree (node, parent) {
|
||||
if (node.tag !== '#') {
|
||||
if (node.text && !node.tag.match(specialTags)) {
|
||||
let el = et.Element('#')
|
||||
const el = et.Element('#')
|
||||
el.text = node.text
|
||||
node._children.unshift(el)
|
||||
delete node.text
|
||||
}
|
||||
if (node.tail) {
|
||||
let el = et.Element('#')
|
||||
const el = et.Element('#')
|
||||
el.text = node.tail
|
||||
let pos = parent._children.indexOf(node) + 1
|
||||
const pos = parent._children.indexOf(node) + 1
|
||||
parent._children.splice(pos, 0, el)
|
||||
delete node.tail
|
||||
}
|
||||
|
@ -84,11 +84,11 @@ function addSpansToNode (node, parent, state) {
|
|||
if (node.tag === '#') {
|
||||
state.segment++
|
||||
|
||||
let sentences = textToSentences(node.text)
|
||||
const sentences = textToSentences(node.text)
|
||||
let pos
|
||||
|
||||
sentences.forEach((sentence) => {
|
||||
let span = createSpan(state.paragraph, state.segment++)
|
||||
const span = createSpan(state.paragraph, state.segment++)
|
||||
span.text = sentence
|
||||
|
||||
// insert the span before the text node
|
||||
|
|
62
src/main.js
62
src/main.js
|
@ -8,15 +8,15 @@ import { saveAs } from 'file-saver'
|
|||
import autosize from 'autosize'
|
||||
import { htmlToText } from './utils'
|
||||
|
||||
m.withAttr = function(attrName, callback, context) {
|
||||
return function(e) {
|
||||
callback.call(context || this, attrName in e.currentTarget ? e.currentTarget[attrName] : e.currentTarget.getAttribute(attrName))
|
||||
}
|
||||
m.withAttr = function (attrName, callback, context) {
|
||||
return function (e) {
|
||||
callback.call(context || this, attrName in e.currentTarget ? e.currentTarget[attrName] : e.currentTarget.getAttribute(attrName))
|
||||
}
|
||||
}
|
||||
|
||||
function blobToDataURL (blob) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let fr = new FileReader()
|
||||
const fr = new FileReader()
|
||||
fr.onloadend = function (e) { resolve(fr.result) }
|
||||
fr.readAsDataURL(blob)
|
||||
})
|
||||
|
@ -24,7 +24,7 @@ function blobToDataURL (blob) {
|
|||
|
||||
function blobToArrayBuffer (blob) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let fr = new FileReader()
|
||||
const fr = new FileReader()
|
||||
fr.onloadend = function (e) { resolve(fr.result) }
|
||||
fr.readAsArrayBuffer(blob)
|
||||
})
|
||||
|
@ -37,23 +37,23 @@ try {
|
|||
pageStoryId = document.location.pathname.match(/^\/story\/(\d*)/)[1]
|
||||
} catch (e) {}
|
||||
|
||||
let logoUrl = chrome.extension.getURL('fimfic2epub-logo.png')
|
||||
const logoUrl = chrome.extension.getURL('fimfic2epub-logo.png')
|
||||
let ffc
|
||||
let stories = document.querySelectorAll('.story_container')
|
||||
const stories = document.querySelectorAll('.story_container')
|
||||
|
||||
stories.forEach((story) => {
|
||||
let id = story.dataset.story
|
||||
const id = story.dataset.story
|
||||
function epubClick (e) {
|
||||
e.preventDefault()
|
||||
openStory(id)
|
||||
}
|
||||
|
||||
let epubButtons = story.querySelectorAll('.drop-down ul li a[title="Download Story (.epub)"]')
|
||||
const epubButtons = story.querySelectorAll('.drop-down ul li a[title="Download Story (.epub)"]')
|
||||
if (epubButtons.length === 0) return
|
||||
for (let i = 0; i < epubButtons.length; i++) {
|
||||
epubButtons[i].addEventListener('click', epubClick, false)
|
||||
}
|
||||
let logo = new Image()
|
||||
const logo = new Image()
|
||||
logo.className = 'fimfic2epub-logo'
|
||||
logo.title = 'Download EPUB with fimfic2epub'
|
||||
logo.src = logoUrl
|
||||
|
@ -61,17 +61,17 @@ stories.forEach((story) => {
|
|||
logo.addEventListener('click', epubClick, false)
|
||||
})
|
||||
|
||||
let cards = document.querySelectorAll('.story-card-container')
|
||||
const cards = document.querySelectorAll('.story-card-container')
|
||||
cards.forEach((card) => {
|
||||
let id
|
||||
let classes = card.className.split(' ')
|
||||
const classes = card.className.split(' ')
|
||||
for (let i = 0; i < classes.length && !id; i++) {
|
||||
let c = classes[i]
|
||||
const c = classes[i]
|
||||
id = c.substring(21)
|
||||
}
|
||||
if (!id) return
|
||||
let flip = card.querySelector('a.card-flip')
|
||||
let epubButton = card.querySelector('a[title="Download .ePub"]')
|
||||
const flip = card.querySelector('a.card-flip')
|
||||
const epubButton = card.querySelector('a[title="Download .ePub"]')
|
||||
if (!epubButton) return
|
||||
epubButton.addEventListener('click', function (e) {
|
||||
e.preventDefault()
|
||||
|
@ -84,7 +84,7 @@ const dialogContainer = document.createElement('div')
|
|||
dialogContainer.id = 'epubDialogContainer'
|
||||
document.body.appendChild(dialogContainer)
|
||||
|
||||
let checkbox = {
|
||||
const checkbox = {
|
||||
view: function ({ attrs, children }) {
|
||||
return m('label.toggleable-switch', [
|
||||
m('input', Object.assign({
|
||||
|
@ -113,10 +113,10 @@ function redraw (arg) {
|
|||
}
|
||||
}
|
||||
|
||||
let ffcProgress = prop(0)
|
||||
let ffcStatus = prop('')
|
||||
const ffcProgress = prop(0)
|
||||
const ffcStatus = prop('')
|
||||
|
||||
let dialog = {
|
||||
const dialog = {
|
||||
oninit () {
|
||||
const ctrl = this
|
||||
|
||||
|
@ -173,7 +173,7 @@ let dialog = {
|
|||
}
|
||||
|
||||
this.setCoverFile = (e) => {
|
||||
let el = e.dom || e.target
|
||||
const el = e.dom || e.target
|
||||
if (el.target) {
|
||||
this.coverUrl('')
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ let dialog = {
|
|||
|
||||
this.setSubjects = function () {
|
||||
// 'this' is the textarea
|
||||
let set = new Set()
|
||||
const set = new Set()
|
||||
ctrl.subjects(this.value.split('\n').map((s) => s.trim()).filter((s) => {
|
||||
if (!s) return false
|
||||
if (set.has(s)) return false
|
||||
|
@ -200,16 +200,16 @@ let dialog = {
|
|||
}
|
||||
|
||||
this.ondown = (e) => {
|
||||
let rect = this.el().firstChild.getBoundingClientRect()
|
||||
let offset = { x: e.pageX - rect.left - document.documentElement.scrollLeft, y: e.pageY - rect.top - document.documentElement.scrollTop }
|
||||
const rect = this.el().firstChild.getBoundingClientRect()
|
||||
const offset = { x: e.pageX - rect.left - document.documentElement.scrollLeft, y: e.pageY - rect.top - document.documentElement.scrollTop }
|
||||
this.dragging(true)
|
||||
let onmove = (e) => {
|
||||
const onmove = (e) => {
|
||||
e.preventDefault()
|
||||
if (this.dragging()) {
|
||||
this.move(e.pageX - offset.x, e.pageY - offset.y)
|
||||
}
|
||||
}
|
||||
let onup = () => {
|
||||
const onup = () => {
|
||||
this.dragging(false)
|
||||
window.removeEventListener('mousemove', onmove)
|
||||
window.removeEventListener('mouseup', onup)
|
||||
|
@ -219,8 +219,8 @@ let dialog = {
|
|||
}
|
||||
|
||||
this.move = (xpos, ypos) => {
|
||||
let bc = document.querySelector('.body_container')
|
||||
let rect = this.el().firstChild.getBoundingClientRect()
|
||||
const bc = document.querySelector('.body_container')
|
||||
const rect = this.el().firstChild.getBoundingClientRect()
|
||||
this.xpos(Math.max(0, Math.min(xpos, bc.offsetWidth - rect.width)))
|
||||
this.ypos(Math.max(0, Math.min(ypos, bc.offsetHeight - rect.height)))
|
||||
this.el().style.left = this.xpos() + 'px'
|
||||
|
@ -228,7 +228,7 @@ let dialog = {
|
|||
}
|
||||
this.center = () => {
|
||||
if (this.dragging()) return
|
||||
let rect = this.el().firstChild.getBoundingClientRect()
|
||||
const rect = this.el().firstChild.getBoundingClientRect()
|
||||
this.move(
|
||||
Math.max(document.documentElement.scrollLeft, (window.innerWidth / 2) - (rect.width / 2) + document.documentElement.scrollLeft),
|
||||
Math.max(document.documentElement.scrollTop, 100 + document.documentElement.scrollTop)
|
||||
|
@ -242,7 +242,7 @@ let dialog = {
|
|||
},
|
||||
|
||||
view (vnode) {
|
||||
let ctrl = vnode.state
|
||||
const ctrl = vnode.state
|
||||
return m('.drop-down-pop-up-container', { oncreate: ctrl.onOpen.bind(ctrl) }, m('.drop-down-pop-up', { style: { 'min-width': '720px' } }, [
|
||||
m('h1', { onmousedown: ctrl.ondown }, m('i.fa.fa-book'), 'Export to EPUB (v' + FIMFIC2EPUB_VERSION + ')', m('a.close_button', { onclick: closeDialog })),
|
||||
m('.drop-down-pop-up-content', [
|
||||
|
@ -295,7 +295,7 @@ let dialog = {
|
|||
ffcProgress() >= 0 ? m('.rating_container',
|
||||
m('.rating-bar', { style: { background: 'rgba(0, 0, 0, 0.2)', 'margin-right': '5px' } }, m('.like-bar', { style: { width: Math.max(0, ffcProgress()) * 100 + '%' } })),
|
||||
' ',
|
||||
ffcProgress() >= 0 && ffcProgress() < 1 ? [ m('i.fa.fa-spin.fa-spinner'), m.trust(' ') ] : null,
|
||||
ffcProgress() >= 0 && ffcProgress() < 1 ? [m('i.fa.fa-spin.fa-spinner'), m.trust(' ')] : null,
|
||||
ffcStatus()
|
||||
) : null,
|
||||
m('div', { style: 'clear: both' })
|
||||
|
|
|
@ -7,8 +7,8 @@ import fileType from 'file-type'
|
|||
|
||||
async function subsetFont (fontPath, glyphs, options = {}) {
|
||||
let data
|
||||
let fontdata = Buffer.from(fontPath, 'binary')
|
||||
let type = fileType(fontdata)
|
||||
const fontdata = Buffer.from(fontPath, 'binary')
|
||||
const type = fileType(fontdata)
|
||||
if (type && type.mime === 'font/ttf') {
|
||||
data = fontdata.buffer
|
||||
} else {
|
||||
|
|
|
@ -18,7 +18,7 @@ function nth (d) {
|
|||
|
||||
export function prettyDate (d) {
|
||||
// format: 27th Oct 2011
|
||||
let months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
|
||||
const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
|
||||
return d.getDate() + nth(d) + ' ' + months[d.getMonth()].substring(0, 3) + ' ' + d.getFullYear()
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ function chapterBars (chapters, currentChapter = -1, highlightCurrent = false) {
|
|||
if (chapters.length <= 1) return null
|
||||
let windowSize = 50
|
||||
let wordCounts = []
|
||||
let highestWordCount = chapters.reduce((max, ch) => {
|
||||
const highestWordCount = chapters.reduce((max, ch) => {
|
||||
wordCounts.push(ch.realWordCount)
|
||||
if (ch.realWordCount > max) return ch.realWordCount
|
||||
return max
|
||||
|
@ -42,9 +42,9 @@ function chapterBars (chapters, currentChapter = -1, highlightCurrent = false) {
|
|||
currentChapter -= start
|
||||
}
|
||||
wordCounts = wordCounts.map((c) => c / highestWordCount)
|
||||
let barWidth = 9
|
||||
let barSpacing = 2
|
||||
let rowSpacing = 9
|
||||
const barWidth = 9
|
||||
const barSpacing = 2
|
||||
const rowSpacing = 9
|
||||
const barCount = Math.min(wordCounts.length, windowSize)
|
||||
const rows = Math.floor(wordCounts.length / barCount) + 1
|
||||
const rowHeight = 30 + rowSpacing
|
||||
|
@ -68,9 +68,9 @@ function chapterBars (chapters, currentChapter = -1, highlightCurrent = false) {
|
|||
}
|
||||
|
||||
export function createChapter (ffc, ch, isNotesChapter) {
|
||||
let { content, notes, notesFirst, title, link, linkNotes, index, showHeadings, showDuration, showWordCount } = ch
|
||||
const { content, notes, notesFirst, title, link, linkNotes, index, showHeadings, showDuration, showWordCount } = ch
|
||||
|
||||
let sections = [
|
||||
const sections = [
|
||||
m.trust(content || ''),
|
||||
notes ? m('div#author_notes', { className: notesFirst ? 'top' : 'bottom' }, [
|
||||
m('p', m('b', 'Author\'s Note:')),
|
||||
|
@ -124,7 +124,7 @@ export function createChapter (ffc, ch, isNotesChapter) {
|
|||
function sortSpineItems (items) {
|
||||
let count = items.length
|
||||
for (let i = 0; i < count; i++) {
|
||||
let item = items[i]
|
||||
const item = items[i]
|
||||
if (!item) {
|
||||
continue
|
||||
}
|
||||
|
@ -140,9 +140,9 @@ function sortSpineItems (items) {
|
|||
}
|
||||
|
||||
export function createOpf (ffc) {
|
||||
let remotes = []
|
||||
const remotes = []
|
||||
// let remoteCounter = 0
|
||||
let remoteCache = new Set()
|
||||
const remoteCache = new Set()
|
||||
ffc.remoteResources.forEach((r, url) => {
|
||||
// remoteCounter++
|
||||
if (!ffc.options.includeExternal) {
|
||||
|
@ -176,18 +176,18 @@ export function createOpf (ffc) {
|
|||
remotes.push(m('item', { id: r.filename, href: r.dest, 'media-type': r.type }))
|
||||
})
|
||||
|
||||
let manifestChapters = ffc.storyInfo.chapters.map((ch, num) =>
|
||||
const 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' : '') + (ffc.options.addChapterBars ? ' svg' : '')).trim() || null })
|
||||
)
|
||||
let spineChapters = ffc.storyInfo.chapters.map((ch, num) =>
|
||||
const spineChapters = ffc.storyInfo.chapters.map((ch, num) =>
|
||||
m('itemref', { idref: 'chapter_' + zeroFill(3, num + 1) })
|
||||
)
|
||||
let manifestNotes = []
|
||||
let spineNotes = []
|
||||
const manifestNotes = []
|
||||
const 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)
|
||||
const 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 }))
|
||||
})
|
||||
|
@ -219,8 +219,8 @@ export function createOpf (ffc) {
|
|||
m('manifest', [
|
||||
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: 'nav', 'href': 'nav.xhtml', 'media-type': 'application/xhtml+xml', properties: 'nav' + (ffc.options.addChapterBars && ffc.storyInfo.chapters.length > 1 ? ' svg' : '') }),
|
||||
ffc.options.includeAuthorNotes && ffc.options.useAuthorNotesIndex && ffc.hasAuthorNotes ? m('item', { id: 'notesnav', 'href': 'notesnav.xhtml', 'media-type': 'application/xhtml+xml' }) : null,
|
||||
m('item', { id: 'nav', href: 'nav.xhtml', 'media-type': 'application/xhtml+xml', properties: 'nav' + (ffc.options.addChapterBars && ffc.storyInfo.chapters.length > 1 ? ' svg' : '') }),
|
||||
ffc.options.includeAuthorNotes && ffc.options.useAuthorNotesIndex && ffc.hasAuthorNotes ? m('item', { id: 'notesnav', href: 'notesnav.xhtml', 'media-type': 'application/xhtml+xml' }) : null,
|
||||
|
||||
m('item', { id: 'style', href: 'Styles/style.css', 'media-type': 'text/css' }),
|
||||
m('item', { id: 'coverstyle', href: 'Styles/coverstyle.css', 'media-type': 'text/css' }),
|
||||
|
@ -255,7 +255,7 @@ export function createOpf (ffc) {
|
|||
|
||||
function navPoints (list) {
|
||||
let playOrder = 1
|
||||
let arr = []
|
||||
const arr = []
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (!list[i]) continue
|
||||
arr.push(m('navPoint', { id: 'navPoint-' + (i + 1), playOrder: playOrder++ }, [
|
||||
|
@ -290,7 +290,7 @@ export function createNcx (ffc) {
|
|||
}
|
||||
|
||||
export function createNav (ffc) {
|
||||
let list = [
|
||||
const list = [
|
||||
m('li', m('a', { href: 'Text/cover.xhtml' }, 'Cover')),
|
||||
m('li', m('a', { href: 'Text/title.xhtml' }, 'Title Page')),
|
||||
ffc.storyInfo.chapters.length > 1 || (ffc.options.includeAuthorNotes && ffc.options.useAuthorNotesIndex && ffc.hasAuthorNotes) ? m('li', m('a', { href: 'nav.xhtml' }, 'Contents')) : null
|
||||
|
@ -299,7 +299,7 @@ export function createNav (ffc) {
|
|||
m('a', { href: 'Text/chapter_' + zeroFill(3, num + 1) + '.xhtml' }, ch.title)
|
||||
])
|
||||
))
|
||||
let prettyList = ffc.storyInfo.chapters.map((ch, num) =>
|
||||
const prettyList = ffc.storyInfo.chapters.map((ch, num) =>
|
||||
m('li.item', [
|
||||
m('.floatbox', m('span.wordcount', ch.realWordCount.toLocaleString('en-GB'))),
|
||||
m('a', { href: 'Text/chapter_' + zeroFill(3, num + 1) + '.xhtml' }, ch.title),
|
||||
|
@ -334,8 +334,8 @@ export function createNav (ffc) {
|
|||
}
|
||||
|
||||
export function createNotesNav (ffc) {
|
||||
let list = ffc.chaptersWithNotes.map((num) => {
|
||||
let ch = ffc.storyInfo.chapters[num]
|
||||
const list = ffc.chaptersWithNotes.map((num) => {
|
||||
const ch = ffc.storyInfo.chapters[num]
|
||||
return m('.item', m('a.leftalign', { href: 'Text/note_' + zeroFill(3, num + 1) + '.xhtml' }, ch.title))
|
||||
})
|
||||
|
||||
|
@ -362,7 +362,7 @@ export function createNotesNav (ffc) {
|
|||
export function createCoverPage (ffc) {
|
||||
let body
|
||||
|
||||
let { width, height } = ffc.coverImageDimensions
|
||||
const { width, height } = ffc.coverImageDimensions
|
||||
|
||||
if (ffc.coverImage) {
|
||||
body = m('svg#cover', { xmlns: NS.SVG, 'xmlns:xlink': NS.XLINK, version: '1.1', viewBox: '0 0 ' + width + ' ' + height },
|
||||
|
@ -402,7 +402,7 @@ function infoBox (heading, data, title) {
|
|||
|
||||
function calcReadingTime (ffc, wordCount = 0) {
|
||||
const wpm = ffc.options.wordsPerMinute
|
||||
let time = (wordCount || ffc.totalWordCount) / wpm
|
||||
const time = (wordCount || ffc.totalWordCount) / wpm
|
||||
let value = 0
|
||||
let unit = ''
|
||||
if (time < 1) {
|
||||
|
|
22
src/utils.js
22
src/utils.js
|
@ -9,13 +9,13 @@ import { unicode } from './constants'
|
|||
export function replaceAsync (str, re, callback) {
|
||||
// http://es5.github.io/#x15.5.4.11
|
||||
str = String(str)
|
||||
let parts = []
|
||||
const parts = []
|
||||
let i = 0
|
||||
if (Object.prototype.toString.call(re) === '[object RegExp]') {
|
||||
if (re.global) { re.lastIndex = i }
|
||||
let m
|
||||
while ((m = re.exec(str))) {
|
||||
let args = m.concat([m.index, m.input])
|
||||
const args = m.concat([m.index, m.input])
|
||||
parts.push(str.slice(i, m.index), callback.apply(null, args))
|
||||
i = re.lastIndex
|
||||
if (!re.global) { break } // for non-global regexes only take the first match
|
||||
|
@ -45,22 +45,22 @@ export function webp2png (data) {
|
|||
webpdecoder = new libwebp.WebPDecoder()
|
||||
}
|
||||
|
||||
let frame = WebPRiffParser(data, 0).frames[0]
|
||||
let width = [0]
|
||||
let height = [0]
|
||||
let decodedData = webpdecoder.WebPDecodeRGBA(
|
||||
const frame = WebPRiffParser(data, 0).frames[0]
|
||||
const width = [0]
|
||||
const height = [0]
|
||||
const decodedData = webpdecoder.WebPDecodeRGBA(
|
||||
data,
|
||||
frame['src_off'], frame['src_size'],
|
||||
frame.src_off, frame.src_size,
|
||||
width, height
|
||||
)
|
||||
|
||||
let png = new PNGPacker({})
|
||||
let buffers = []
|
||||
const png = new PNGPacker({})
|
||||
const buffers = []
|
||||
png.on('data', (chunk) => {
|
||||
buffers.push(chunk)
|
||||
})
|
||||
png.once('end', () => {
|
||||
let pngData = Buffer.concat(buffers)
|
||||
const pngData = Buffer.concat(buffers)
|
||||
resolve(pngData)
|
||||
})
|
||||
png.pack(decodedData, width[0], height[0])
|
||||
|
@ -122,7 +122,7 @@ export async function readingEase (text, wakeupInterval = Infinity, progresscb)
|
|||
let lastTime = Date.now()
|
||||
|
||||
for (let i = 0; i < tokenSentences.length; i++) {
|
||||
let now = Date.now()
|
||||
const now = Date.now()
|
||||
if (lastTime + wakeupInterval < now) {
|
||||
lastTime = now
|
||||
if (typeof progresscb === 'function') {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import path from 'path'
|
||||
import nodeExternals from 'webpack-node-externals'
|
||||
|
||||
let inProduction = process.env.NODE_ENV === 'production' || process.argv.indexOf('-p') !== -1
|
||||
const inProduction = process.env.NODE_ENV === 'production' || process.argv.indexOf('-p') !== -1
|
||||
|
||||
const bundleExtensionConfig = {
|
||||
entry: {
|
||||
|
|
Loading…
Reference in a new issue