mirror of
https://github.com/daniel-j/fimfic2epub.git
synced 2024-05-14 01:13:50 +12:00
standard js
This commit is contained in:
parent
8452cba7fc
commit
01c60253fd
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
|||
node_modules/
|
||||
out.epub
|
||||
extension/fimfic2epub.js
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["https://www.fimfiction.net/story/*"],
|
||||
"matches": ["https://www.fimfiction.net/story/*", "http://www.fimfiction.net/story/*"],
|
||||
"js": ["tidy.js", "fimfic2epub.js"]
|
||||
}
|
||||
],
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,17 +1,15 @@
|
|||
'use strict'
|
||||
|
||||
|
||||
// gulp and utilities
|
||||
import gulp from 'gulp'
|
||||
import gutil from 'gulp-util'
|
||||
import del from 'del'
|
||||
import mergeStream from 'merge-stream'
|
||||
import Sequence from 'run-sequence'
|
||||
import watch from 'gulp-watch'
|
||||
import lazypipe from 'lazypipe'
|
||||
|
||||
// script
|
||||
import eslint from 'gulp-eslint'
|
||||
import standard from 'gulp-standard'
|
||||
import webpack from 'webpack'
|
||||
import webpackConfig from './webpack.config.babel.js'
|
||||
|
||||
|
@ -19,100 +17,82 @@ const sequence = Sequence.use(gulp)
|
|||
|
||||
let inProduction = process.env.NODE_ENV === 'production' || process.argv.indexOf('-p') !== -1
|
||||
|
||||
let eslintOpts = {
|
||||
envs: ['browser', 'node'],
|
||||
rules: {
|
||||
'strict': 0,
|
||||
'semi': [1, 'never'],
|
||||
'quotes': [1, 'single'],
|
||||
'space-infix-ops': [0, {'int32Hint': true}],
|
||||
'no-empty': 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let watchOpts = {
|
||||
readDelay: 500,
|
||||
verbose: true
|
||||
readDelay: 500,
|
||||
verbose: true
|
||||
}
|
||||
|
||||
if (inProduction) {
|
||||
webpackConfig.plugins.push(new webpack.optimize.DedupePlugin())
|
||||
webpackConfig.plugins.push(new webpack.optimize.OccurenceOrderPlugin(false))
|
||||
webpackConfig.plugins.push(new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
warnings: false,
|
||||
screw_ie8: true
|
||||
},
|
||||
comments: false,
|
||||
mangle: {
|
||||
screw_ie8: true
|
||||
},
|
||||
screw_ie8: true,
|
||||
sourceMap: false
|
||||
}))
|
||||
webpackConfig.plugins.push(new webpack.optimize.DedupePlugin())
|
||||
webpackConfig.plugins.push(new webpack.optimize.OccurenceOrderPlugin(false))
|
||||
webpackConfig.plugins.push(new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
warnings: false,
|
||||
screw_ie8: true
|
||||
},
|
||||
comments: false,
|
||||
mangle: {
|
||||
screw_ie8: true
|
||||
},
|
||||
screw_ie8: true,
|
||||
sourceMap: false
|
||||
}))
|
||||
}
|
||||
|
||||
let wpCompiler = webpack(Object.assign({}, webpackConfig, {
|
||||
cache: {},
|
||||
devtool: inProduction? null:'inline-source-map',
|
||||
debug: !inProduction
|
||||
cache: {},
|
||||
devtool: inProduction ? null : 'inline-source-map',
|
||||
debug: !inProduction
|
||||
}))
|
||||
|
||||
function webpackTask(callback) {
|
||||
// run webpack
|
||||
wpCompiler.run(function(err, stats) {
|
||||
if(err) throw new gutil.PluginError('webpack', err)
|
||||
gutil.log('[webpack]', stats.toString({
|
||||
colors: true,
|
||||
hash: false,
|
||||
version: false,
|
||||
chunks: false,
|
||||
chunkModules: false
|
||||
}))
|
||||
callback()
|
||||
})
|
||||
function webpackTask (callback) {
|
||||
// run webpack
|
||||
wpCompiler.run(function (err, stats) {
|
||||
if (err) throw new gutil.PluginError('webpack', err)
|
||||
gutil.log('[webpack]', stats.toString({
|
||||
colors: true,
|
||||
hash: false,
|
||||
version: false,
|
||||
chunks: false,
|
||||
chunkModules: false
|
||||
}))
|
||||
callback()
|
||||
})
|
||||
}
|
||||
|
||||
let lintPipe = lazypipe()
|
||||
.pipe(standard)
|
||||
.pipe(standard.reporter, 'default', {
|
||||
breakOnError: false
|
||||
})
|
||||
|
||||
let lintESPipe = lazypipe()
|
||||
.pipe(eslint, eslintOpts)
|
||||
.pipe(eslint.format)
|
||||
|
||||
// Cleanup tasks
|
||||
gulp.task('clean', () => del('build'))
|
||||
|
||||
gulp.task('clean:script', () => {
|
||||
return del('build/script')
|
||||
})
|
||||
|
||||
// Cleanup task
|
||||
gulp.task('clean', () => del('extension/fimfic2epub.js'))
|
||||
|
||||
// Main tasks
|
||||
gulp.task('webpack', webpackTask)
|
||||
gulp.task('script', ['webpack'])
|
||||
gulp.task('watch:script', () => {
|
||||
return watch(['src/**/*.js'], watchOpts, function () {
|
||||
return sequence('script')
|
||||
})
|
||||
return watch(['src/**/*.js'], watchOpts, function () {
|
||||
return sequence('script')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
gulp.task('lint', () => {
|
||||
return gulp.src(['src/**/*.js']).pipe(lintESPipe())
|
||||
return gulp.src(['gulpfile.babel.js', 'webpack.config.babel.js', 'src/**/*.js']).pipe(lintPipe())
|
||||
})
|
||||
gulp.task('watch:lint', () => {
|
||||
return watch(['src/**/*.js'], watchOpts, function (file) {
|
||||
gulp.src(file.path).pipe(lintESPipe())
|
||||
})
|
||||
return watch(['src/**/*.js'], watchOpts, function (file) {
|
||||
gulp.src(file.path).pipe(lintPipe())
|
||||
})
|
||||
})
|
||||
|
||||
// Default task
|
||||
gulp.task('default', (done) => {
|
||||
sequence('clean', ['script', 'lint'], done)
|
||||
sequence('clean', ['script', 'lint'], done)
|
||||
})
|
||||
|
||||
// Watch task
|
||||
gulp.task('watch', (done) => {
|
||||
sequence('default', ['watch:lint', 'watch:script'], done)
|
||||
})
|
||||
sequence('default', ['watch:lint', 'watch:script'], done)
|
||||
})
|
||||
|
|
13
package.json
13
package.json
|
@ -11,8 +11,7 @@
|
|||
"jszip": "^3.0.0",
|
||||
"mithril": "^0.2.5",
|
||||
"pretty-data": "^0.40.0",
|
||||
"tidy-html5": "^0.1.1",
|
||||
"xhr2": "^0.1.3"
|
||||
"tidy-html5": "^0.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.9.1",
|
||||
|
@ -22,12 +21,18 @@
|
|||
"babel-preset-node6": "^11.0.0",
|
||||
"del": "^2.2.0",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-eslint": "^2.0.0",
|
||||
"gulp-standard": "^7.0.1",
|
||||
"gulp-util": "^3.0.7",
|
||||
"gulp-watch": "^4.3.8",
|
||||
"lazypipe": "^1.0.1",
|
||||
"merge-stream": "^1.0.0",
|
||||
"run-sequence": "^1.2.1",
|
||||
"standard": "^7.1.2",
|
||||
"webpack": "^1.13.1"
|
||||
},
|
||||
"standard": {
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
856
src/main.js
856
src/main.js
|
@ -1,3 +1,4 @@
|
|||
/* global tidy, chrome */
|
||||
'use strict'
|
||||
|
||||
import m from 'mithril'
|
||||
|
@ -8,43 +9,35 @@ import { XmlEntities } from 'html-entities'
|
|||
import { saveAs } from 'file-saver'
|
||||
|
||||
const entities = new XmlEntities()
|
||||
const tidy = tidy_html5
|
||||
|
||||
//const XMLHttpRequest = require('xhr2')
|
||||
|
||||
let beautifyOptions = {
|
||||
indent_size: 2,
|
||||
wrap_attributes: false
|
||||
}
|
||||
|
||||
const NS = {
|
||||
OPF: 'http://www.idpf.org/2007/opf',
|
||||
OPS: 'http://www.idpf.org/2007/ops',
|
||||
DC: 'http://purl.org/dc/elements/1.1/',
|
||||
DAISY: 'http://www.daisy.org/z3986/2005/ncx/',
|
||||
XHTML: 'http://www.w3.org/1999/xhtml',
|
||||
SVG: 'http://www.w3.org/2000/svg',
|
||||
XLINK: 'http://www.w3.org/1999/xlink'
|
||||
OPF: 'http://www.idpf.org/2007/opf',
|
||||
OPS: 'http://www.idpf.org/2007/ops',
|
||||
DC: 'http://purl.org/dc/elements/1.1/',
|
||||
DAISY: 'http://www.daisy.org/z3986/2005/ncx/',
|
||||
XHTML: 'http://www.w3.org/1999/xhtml',
|
||||
SVG: 'http://www.w3.org/2000/svg',
|
||||
XLINK: 'http://www.w3.org/1999/xlink'
|
||||
}
|
||||
|
||||
let tidyOptions = {
|
||||
'indent': 'auto',
|
||||
'numeric-entities': 'yes',
|
||||
'output-xhtml': 'yes',
|
||||
'alt-text': 'Image',
|
||||
'wrap': '0',
|
||||
'quiet': 'yes'
|
||||
'indent': 'auto',
|
||||
'numeric-entities': 'yes',
|
||||
'output-xhtml': 'yes',
|
||||
'alt-text': 'Image',
|
||||
'wrap': '0',
|
||||
'quiet': 'yes'
|
||||
}
|
||||
|
||||
let mimeMap = {
|
||||
'image/jpeg': 'Images/*.jpg',
|
||||
'image/png': 'Images/*.png',
|
||||
'image/gif': 'Images/*.gif'
|
||||
'image/jpeg': 'Images/*.jpg',
|
||||
'image/png': 'Images/*.png',
|
||||
'image/gif': 'Images/*.gif'
|
||||
}
|
||||
|
||||
//const STORY_ID = 180690 // bbcode test tags
|
||||
//const STORY_ID = 931 // pink eyes
|
||||
//const STORY_ID = 119190 // fallout equestria
|
||||
// const STORY_ID = 180690 // bbcode test tags
|
||||
// const STORY_ID = 931 // pink eyes
|
||||
// const STORY_ID = 119190 // fallout equestria
|
||||
const STORY_ID = document.location.pathname.match(/^\/story\/(\d*)/)[1]
|
||||
|
||||
let apiUrl = 'https://www.fimfiction.net/api/story.php?story=' + STORY_ID
|
||||
|
@ -58,258 +51,252 @@ let isDownloading = false
|
|||
let cachedBlob = null
|
||||
|
||||
if (epubButton) {
|
||||
epubButton.addEventListener('click', function (e) {
|
||||
e.preventDefault()
|
||||
if (isDownloading) {
|
||||
return
|
||||
}
|
||||
if (cachedBlob) {
|
||||
saveStory()
|
||||
return
|
||||
}
|
||||
downloadStory()
|
||||
}, false)
|
||||
epubButton.addEventListener('click', function (e) {
|
||||
e.preventDefault()
|
||||
if (isDownloading) {
|
||||
return
|
||||
}
|
||||
if (cachedBlob) {
|
||||
saveStory()
|
||||
return
|
||||
}
|
||||
downloadStory()
|
||||
}, false)
|
||||
}
|
||||
|
||||
function fetch(url, cb, type) {
|
||||
if (url.indexOf('//') === 0) {
|
||||
url = 'http:'+url
|
||||
}
|
||||
let x = new XMLHttpRequest()
|
||||
x.open('get', url, true)
|
||||
if (type) {
|
||||
x.responseType = type
|
||||
}
|
||||
x.onload = function () {
|
||||
cb(x.response, x.getResponseHeader('content-type'))
|
||||
}
|
||||
x.onerror = function () {
|
||||
cb(null)
|
||||
}
|
||||
x.send()
|
||||
function fetch (url, cb, type) {
|
||||
if (url.indexOf('//') === 0) {
|
||||
url = 'http:' + url
|
||||
}
|
||||
let x = new XMLHttpRequest()
|
||||
x.open('get', url, true)
|
||||
if (type) {
|
||||
x.responseType = type
|
||||
}
|
||||
x.onload = function () {
|
||||
cb(x.response, x.getResponseHeader('content-type'))
|
||||
}
|
||||
x.onerror = function () {
|
||||
cb(null)
|
||||
}
|
||||
x.send()
|
||||
}
|
||||
|
||||
function fetchChapters(cb) {
|
||||
let chapters = storyInfo.chapters
|
||||
let chapterCount = storyInfo.chapters.length
|
||||
let currentChapter = 0
|
||||
function recursive() {
|
||||
let ch = chapters[currentChapter]
|
||||
console.log('Fetching chapter '+ch.id+' '+ch.title)
|
||||
fetch(ch.link.replace('http', 'https'), function (html) {
|
||||
html = parseChapter(ch, html)
|
||||
chapterContent[ch.id] = html
|
||||
currentChapter++
|
||||
if (currentChapter < chapterCount) {
|
||||
recursive()
|
||||
} else {
|
||||
cb()
|
||||
}
|
||||
})
|
||||
}
|
||||
recursive()
|
||||
function fetchChapters (cb) {
|
||||
let chapters = storyInfo.chapters
|
||||
let chapterCount = storyInfo.chapters.length
|
||||
let currentChapter = 0
|
||||
function recursive () {
|
||||
let ch = chapters[currentChapter]
|
||||
console.log('Fetching chapter ' + ch.id + ' ' + ch.title)
|
||||
fetch(ch.link.replace('http', 'https'), function (html) {
|
||||
html = parseChapter(ch, html)
|
||||
chapterContent[ch.id] = html
|
||||
currentChapter++
|
||||
if (currentChapter < chapterCount) {
|
||||
recursive()
|
||||
} else {
|
||||
cb()
|
||||
}
|
||||
})
|
||||
}
|
||||
recursive()
|
||||
}
|
||||
|
||||
function fetchRemote(cb) {
|
||||
let iter = remoteResources.entries()
|
||||
let counter = 0
|
||||
function fetchRemote (cb) {
|
||||
let iter = remoteResources.entries()
|
||||
let counter = 0
|
||||
|
||||
function recursive() {
|
||||
let r = iter.next().value
|
||||
if (!r) {
|
||||
cb()
|
||||
return
|
||||
}
|
||||
let url = r[0]
|
||||
r = r[1]
|
||||
console.log('Fetching remote file '+r.filename, url)
|
||||
chrome.runtime.sendMessage(url, function (objUrl) {
|
||||
if (objUrl) {
|
||||
fetch(objUrl, function (data, type) {
|
||||
r.dest = null
|
||||
r.type = type
|
||||
let dest = mimeMap[type]
|
||||
function recursive () {
|
||||
let r = iter.next().value
|
||||
if (!r) {
|
||||
cb()
|
||||
return
|
||||
}
|
||||
let url = r[0]
|
||||
r = r[1]
|
||||
console.log('Fetching remote file ' + r.filename, url)
|
||||
chrome.runtime.sendMessage(url, function (objUrl) {
|
||||
if (objUrl) {
|
||||
fetch(objUrl, function (data, type) {
|
||||
r.dest = null
|
||||
r.type = type
|
||||
let dest = mimeMap[type]
|
||||
|
||||
if (dest) {
|
||||
r.dest = dest.replace('*', r.filename)
|
||||
zip.file(r.dest, data)
|
||||
}
|
||||
URL.revokeObjectURL(objUrl)
|
||||
counter++
|
||||
recursive()
|
||||
}, 'arraybuffer')
|
||||
} else {
|
||||
counter++
|
||||
recursive()
|
||||
}
|
||||
})
|
||||
}
|
||||
recursive()
|
||||
if (dest) {
|
||||
r.dest = dest.replace('*', r.filename)
|
||||
zip.file(r.dest, data)
|
||||
}
|
||||
URL.revokeObjectURL(objUrl)
|
||||
counter++
|
||||
recursive()
|
||||
}, 'arraybuffer')
|
||||
} else {
|
||||
counter++
|
||||
recursive()
|
||||
}
|
||||
})
|
||||
}
|
||||
recursive()
|
||||
}
|
||||
|
||||
function downloadStory() {
|
||||
isDownloading = true
|
||||
console.log('Fetching story...')
|
||||
fetch(apiUrl, function (raw) {
|
||||
function downloadStory () {
|
||||
isDownloading = true
|
||||
console.log('Fetching story...')
|
||||
|
||||
let data
|
||||
try {
|
||||
data = JSON.parse(raw)
|
||||
} catch (e) {
|
||||
console.log('Unable to fetch story json')
|
||||
return
|
||||
}
|
||||
storyInfo = data.story
|
||||
storyInfo.uuid = 'urn:fimfiction:'+storyInfo.id
|
||||
storyInfo.publishDate = '1970-01-01' // TODO!
|
||||
console.log(storyInfo)
|
||||
remoteResources.set(storyInfo.full_image, {filename: 'cover'})
|
||||
let coverImage = new Image()
|
||||
coverImage.src = storyInfo.full_image
|
||||
coverImage.addEventListener('load', function () {
|
||||
|
||||
fetch(apiUrl, function (raw) {
|
||||
let data
|
||||
try {
|
||||
data = JSON.parse(raw)
|
||||
} catch (e) {
|
||||
console.log('Unable to fetch story json')
|
||||
return
|
||||
}
|
||||
storyInfo = data.story
|
||||
storyInfo.uuid = 'urn:fimfiction:' + storyInfo.id
|
||||
storyInfo.publishDate = '1970-01-01' // TODO!
|
||||
console.log(storyInfo)
|
||||
remoteResources.set(storyInfo.full_image, {filename: 'cover'})
|
||||
let coverImage = new Image()
|
||||
coverImage.src = storyInfo.full_image
|
||||
|
||||
zip.file('toc.ncx', createNcx())
|
||||
zip.file('nav.xhtml', createNav())
|
||||
coverImage.addEventListener('load', function () {
|
||||
zip.file('toc.ncx', createNcx())
|
||||
zip.file('nav.xhtml', createNav())
|
||||
|
||||
fetchChapters(function () {
|
||||
fetchRemote(function () {
|
||||
fetchChapters(function () {
|
||||
fetchRemote(function () {
|
||||
remoteResources.forEach((r, url) => {
|
||||
if (r.chapter && r.originalUrl && r.dest) {
|
||||
chapterContent[r.chapter] = chapterContent[r.chapter].replace(
|
||||
new RegExp(escapeStringRegexp(r.originalUrl), 'g'),
|
||||
r.dest
|
||||
)
|
||||
} else {
|
||||
r.remote = true
|
||||
}
|
||||
})
|
||||
|
||||
remoteResources.forEach((r, url) => {
|
||||
if (r.chapter && r.originalUrl && r.dest) {
|
||||
chapterContent[r.chapter] = chapterContent[r.chapter].replace(
|
||||
new RegExp(escapeStringRegexp(r.originalUrl), 'g'),
|
||||
r.dest
|
||||
)
|
||||
} else {
|
||||
r.remote = true
|
||||
}
|
||||
})
|
||||
for (let id in chapterContent) {
|
||||
let html = chapterContent[id]
|
||||
let filename = 'chapter_' + id + '.xhtml'
|
||||
zip.file(filename, html)
|
||||
}
|
||||
|
||||
for (let id in chapterContent) {
|
||||
let html = chapterContent[id]
|
||||
let filename = 'chapter_'+id+'.xhtml'
|
||||
zip.file(filename, html)
|
||||
}
|
||||
zip.file('cover.xhtml', createCoverPage(coverImage.width, coverImage.height))
|
||||
zip.file('content.opf', createOpf())
|
||||
|
||||
zip.file('cover.xhtml', createCoverPage(coverImage.width, coverImage.height))
|
||||
zip.file('content.opf', createOpf())
|
||||
/*
|
||||
zip
|
||||
.generateNodeStream({
|
||||
type: 'nodebuffer',
|
||||
streamFiles: true,
|
||||
mimeType: 'application/epub+zip',
|
||||
compression: 'DEFLATE',
|
||||
compressionOptions: {level: 9}
|
||||
})
|
||||
.pipe(fs.createWriteStream('out.epub'))
|
||||
.on('finish', function () {
|
||||
// JSZip generates a readable stream with a "end" event,
|
||||
// but is piped here in a writable stream which emits a "finish" event.
|
||||
console.log("out.epub written.");
|
||||
})
|
||||
*/
|
||||
|
||||
/*zip
|
||||
.generateNodeStream({
|
||||
type: 'nodebuffer',
|
||||
streamFiles: true,
|
||||
mimeType: 'application/epub+zip',
|
||||
compression: 'DEFLATE',
|
||||
compressionOptions: {level: 9}
|
||||
})
|
||||
.pipe(fs.createWriteStream('out.epub'))
|
||||
.on('finish', function () {
|
||||
// JSZip generates a readable stream with a "end" event,
|
||||
// but is piped here in a writable stream which emits a "finish" event.
|
||||
console.log("out.epub written.");
|
||||
})*/
|
||||
zip
|
||||
.generateAsync({
|
||||
type: 'blob',
|
||||
mimeType: 'application/epub+zip',
|
||||
compression: 'DEFLATE',
|
||||
compressionOptions: {level: 9}
|
||||
})
|
||||
.then((blob) => {
|
||||
cachedBlob = blob
|
||||
saveStory()
|
||||
isDownloading = false
|
||||
})
|
||||
|
||||
})
|
||||
console.log('packing epub...')
|
||||
|
||||
|
||||
})
|
||||
}, false)
|
||||
})
|
||||
zip
|
||||
.generateAsync({
|
||||
type: 'blob',
|
||||
mimeType: 'application/epub+zip',
|
||||
compression: 'DEFLATE',
|
||||
compressionOptions: {level: 9}
|
||||
})
|
||||
.then((blob) => {
|
||||
cachedBlob = blob
|
||||
saveStory()
|
||||
isDownloading = false
|
||||
})
|
||||
})
|
||||
})
|
||||
}, false)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function saveStory() {
|
||||
saveAs(cachedBlob, storyInfo.title+' by '+storyInfo.author.name+'.epub')
|
||||
function saveStory () {
|
||||
saveAs(cachedBlob, storyInfo.title + ' by ' + storyInfo.author.name + '.epub')
|
||||
}
|
||||
|
||||
//const parse5 = require('parse5')
|
||||
//const xmlserializer = require('xmlserializer')
|
||||
function parseChapter (ch, html) {
|
||||
let chapterPage = '<!doctype html>' + render(
|
||||
m('html', {xmlns: NS.XHTML}, [
|
||||
m('head', [
|
||||
m('meta', {charset: 'utf-8'}),
|
||||
m('link', {rel: 'stylesheet', type: 'text/css', href: 'style.css'}),
|
||||
m('title', ch.title)
|
||||
]),
|
||||
m('body', [
|
||||
m('div', {id: 'chapter_container'}, '@@CHAPTER@@'),
|
||||
m('div', {id: 'author_notes'}, '@@NOTES@@')
|
||||
])
|
||||
])
|
||||
)
|
||||
|
||||
//let html = fs.readFileSync('chapter.html', 'utf8')
|
||||
function parseChapter(ch, html) {
|
||||
let chapterTitle = html.match(/<a\s+[^>]*id="chapter_title"[^>]*>(.*?)<\/a>/)
|
||||
|
||||
let chapterPage = `<!doctype html>`+render(
|
||||
m('html', {xmlns: NS.XHTML}, [
|
||||
m('head', [
|
||||
m('meta', {charset: 'utf-8'}),
|
||||
m('link', {rel: 'stylesheet', type: 'text/css', href: 'style.css'}),
|
||||
m('title', ch.title)
|
||||
]),
|
||||
m('body', [
|
||||
m('div', {id: 'chapter_container'}, '@@CHAPTER@@'),
|
||||
m('div', {id: 'author_notes'}, '@@NOTES@@')
|
||||
])
|
||||
])
|
||||
)
|
||||
if (!chapterTitle) {
|
||||
return tidy('<?xml version="1.0" encoding="utf-8"?>\n' + chapterPage, tidyOptions)
|
||||
}
|
||||
chapterTitle = chapterTitle[1]
|
||||
|
||||
let chapterTitle = html.match(/<a\s+[^>]*id="chapter_title"[^>]*>(.*?)<\/a>/)
|
||||
let chapterPos = html.indexOf('<div id="chapter_container">')
|
||||
let chapter = html.substring(chapterPos + 29)
|
||||
|
||||
if (!chapterTitle) {
|
||||
return tidy(`<?xml version="1.0" encoding="utf-8"?>\n`+chapterPage, tidyOptions)
|
||||
}
|
||||
chapterTitle = chapterTitle[1]
|
||||
let pos = chapter.indexOf('\t</div>\t\t\n\t')
|
||||
|
||||
let chapterPos = html.indexOf('<div id="chapter_container">')
|
||||
let chapter = html.substring(chapterPos+29)
|
||||
let authorNotesPos = chapter.substring(pos).indexOf('<b>Author\'s Note:</b>')
|
||||
let authorNotes = ''
|
||||
if (authorNotesPos !== -1) {
|
||||
authorNotes = chapter.substring(pos + authorNotesPos + 22)
|
||||
authorNotes = authorNotes.substring(0, authorNotes.indexOf('\t\t\n\t</div>'))
|
||||
}
|
||||
|
||||
let pos = chapter.indexOf('\t</div>\t\t\n\t')
|
||||
chapter = chapter.substring(0, pos)
|
||||
|
||||
let authorNotesPos = chapter.substring(pos).indexOf('<b>Author\'s Note:</b>')
|
||||
let authorNotes = ''
|
||||
if (authorNotesPos !== -1) {
|
||||
authorNotes = chapter.substring(pos+authorNotesPos+22)
|
||||
authorNotes = authorNotes.substring(0, authorNotes.indexOf('\t\t\n\t</div>'))
|
||||
}
|
||||
chapterPage = chapterPage.replace('@@CHAPTER@@', chapter)
|
||||
chapterPage = chapterPage.replace('@@NOTES@@', authorNotes)
|
||||
|
||||
chapter = chapter.substring(0, pos)
|
||||
chapterPage = chapterPage.replace(/<center>/g, '<div style="text-align: center;">')
|
||||
chapterPage = chapterPage.replace(/<\/center>/g, '</div>')
|
||||
|
||||
chapterPage = chapterPage.replace('@@CHAPTER@@', chapter)
|
||||
chapterPage = chapterPage.replace('@@NOTES@@', authorNotes)
|
||||
chapterPage = chapterPage.replace(/<div class="youtube_container">(.+?)<\/div>/g, function (match, contents, offset) {
|
||||
// console.log(match, contents, offset)
|
||||
let youtubeId = contents.match(/src="https:\/\/www.youtube.com\/embed\/(.+?)"/)[1]
|
||||
let thumbnail = 'http://img.youtube.com/vi/' + youtubeId + '/hqdefault.jpg'
|
||||
let youtubeUrl = 'https://youtube.com/watch?v=' + youtubeId
|
||||
return render(m('a', {href: youtubeUrl, target: '_blank'},
|
||||
m('img', {src: thumbnail, alt: 'Youtube Video'})
|
||||
))
|
||||
})
|
||||
|
||||
chapterPage = chapterPage.replace(/<center>/g, '<div style="text-align: center;">')
|
||||
chapterPage = chapterPage.replace(/<\/center>/g, '</div>')
|
||||
chapterPage = chapterPage.replace('<blockquote style="margin: 10px 0px; box-sizing:border-box; -moz-box-sizing:border-box;margin-right:25px; padding: 15px;background-color: #F7F7F7;border: 1px solid #AAA;width: 50%;float:left;box-shadow: 5px 5px 0px #EEE;">', '<blockquote class="left_insert">')
|
||||
chapterPage = chapterPage.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">')
|
||||
|
||||
chapterPage = chapterPage.replace(/<div class="youtube_container">(.+?)<\/div>/g, function (match, contents, offset) {
|
||||
//console.log(match, contents, offset)
|
||||
let youtubeId = contents.match(/src="https:\/\/www.youtube.com\/embed\/(.+?)"/)[1]
|
||||
let thumbnail = 'http://img.youtube.com/vi/'+youtubeId+'/hqdefault.jpg'
|
||||
let youtubeUrl = 'https://youtube.com/watch?v='+youtubeId
|
||||
return render(m('a', {href: youtubeUrl, target: '_blank'},
|
||||
m('img', {src: thumbnail, alt: 'Youtube Video'})
|
||||
))
|
||||
})
|
||||
chapterPage = tidy(`<?xml version="1.0" encoding="utf-8"?>\n` + chapterPage, tidyOptions)
|
||||
|
||||
chapterPage = chapterPage.replace('<blockquote style="margin: 10px 0px; box-sizing:border-box; -moz-box-sizing:border-box;margin-right:25px; padding: 15px;background-color: #F7F7F7;border: 1px solid #AAA;width: 50%;float:left;box-shadow: 5px 5px 0px #EEE;">', '<blockquote class="left_insert">')
|
||||
chapterPage = chapterPage.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">')
|
||||
let remoteCounter = 1
|
||||
chapterPage = chapterPage.replace(/(<img src=")(.+?)("[^>]*>)/g, function (match, first, url, last) {
|
||||
let cleanurl = decodeURI(entities.decode(url))
|
||||
if (remoteResources.has(cleanurl)) {
|
||||
return match
|
||||
}
|
||||
let filename = 'ch' + ch.id + '_' + remoteCounter
|
||||
remoteCounter++
|
||||
remoteResources.set(cleanurl, {filename: filename, chapter: ch.id, originalUrl: url})
|
||||
return match
|
||||
})
|
||||
|
||||
chapterPage = tidy(`<?xml version="1.0" encoding="utf-8"?>\n`+chapterPage, tidyOptions)
|
||||
|
||||
let remoteCounter = 1
|
||||
chapterPage = chapterPage.replace(/(<img src=")(.+?)("[^>]*>)/g, function (match, first, url, last) {
|
||||
let cleanurl = decodeURI(entities.decode(url))
|
||||
if (remoteResources.has(cleanurl)) {
|
||||
return match
|
||||
}
|
||||
let filename = 'ch'+ch.id+'_'+remoteCounter
|
||||
remoteCounter++
|
||||
remoteResources.set(cleanurl, {filename: filename, chapter: ch.id, originalUrl: url})
|
||||
return match
|
||||
})
|
||||
|
||||
return chapterPage
|
||||
return chapterPage
|
||||
}
|
||||
|
||||
const JSZip = require('jszip')
|
||||
|
@ -320,258 +307,247 @@ zip.file('mimetype', 'application/epub+zip')
|
|||
|
||||
zip.folder('META-INF').file('container.xml', `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
|
||||
<rootfiles>
|
||||
<rootfile full-path="content.opf" media-type="application/oebps-package+xml"/>
|
||||
</rootfiles>
|
||||
<rootfiles>
|
||||
<rootfile full-path="content.opf" media-type="application/oebps-package+xml"/>
|
||||
</rootfiles>
|
||||
</container>
|
||||
`)
|
||||
|
||||
|
||||
function subjects(s) {
|
||||
var list = []
|
||||
for (let i = 0; i < s.length; i++) {
|
||||
list.push(m('dc:subject', s[i]))
|
||||
}
|
||||
return list
|
||||
function subjects (s) {
|
||||
var list = []
|
||||
for (let i = 0; i < s.length; i++) {
|
||||
list.push(m('dc:subject', s[i]))
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
function createOpf() {
|
||||
function createOpf () {
|
||||
let remotes = []
|
||||
remoteResources.forEach((r, url) => {
|
||||
if (!r.dest) {
|
||||
return
|
||||
}
|
||||
let attrs = {id: r.filename, href: r.dest, 'media-type': r.type}
|
||||
if (r.filename === 'cover') {
|
||||
attrs.properties = 'cover-image'
|
||||
}
|
||||
remotes.push(m('item', attrs))
|
||||
})
|
||||
|
||||
let remotes = []
|
||||
remoteResources.forEach((r, url) => {
|
||||
if (!r.dest) {
|
||||
return
|
||||
}
|
||||
let attrs = {id: r.filename, href: r.dest, 'media-type': r.type}
|
||||
if (r.filename === 'cover') {
|
||||
attrs.properties = 'cover-image'
|
||||
}
|
||||
remotes.push(m('item', attrs))
|
||||
})
|
||||
let contentOpf = '<?xml version="1.0" encoding="utf-8"?>\n' + pretty.xml(render(
|
||||
m('package', {xmlns: NS.OPF, version: '3.0', 'unique-identifier': 'BookId'}, [
|
||||
m('metadata', {'xmlns:dc': NS.DC, 'xmlns:opf': NS.OPF}, [
|
||||
m('dc:identifier', {id: 'BookId'}, storyInfo.uuid),
|
||||
m('dc:title', storyInfo.title),
|
||||
m('dc:creator', {id: 'cre'}, storyInfo.author.name),
|
||||
m('meta', {refines: '#cre', property: 'role', scheme: 'marc:relators'}, 'aut'),
|
||||
m('dc:date', storyInfo.publishDate),
|
||||
m('dc:publisher', 'Fimfiction'),
|
||||
m('dc:description', storyInfo.description),
|
||||
m('dc:source', storyInfo.url),
|
||||
m('dc:language', 'en'),
|
||||
m('meta', {name: 'cover', content: 'cover'}),
|
||||
m('meta', {property: 'dcterms:modified'}, new Date(storyInfo.date_modified * 1000).toISOString().replace('.000', ''))
|
||||
].concat(subjects(['Fiction', 'Pony']))),
|
||||
|
||||
let contentOpf = `<?xml version="1.0" encoding="utf-8"?>
|
||||
`+pretty.xml(render(
|
||||
m('package', {xmlns: NS.OPF, version: '3.0', 'unique-identifier': 'BookId'}, [
|
||||
m('metadata', {'xmlns:dc': NS.DC, 'xmlns:opf': NS.OPF}, [
|
||||
m('dc:identifier', {id: 'BookId'}, storyInfo.uuid),
|
||||
m('dc:title', storyInfo.title),
|
||||
m('dc:creator', {id: 'cre'}, storyInfo.author.name),
|
||||
m('meta', {refines: '#cre', property: 'role', scheme: 'marc:relators'}, 'aut'),
|
||||
m('dc:date', storyInfo.publishDate),
|
||||
m('dc:publisher', 'Fimfiction'),
|
||||
m('dc:description', storyInfo.description),
|
||||
m('dc:source', storyInfo.url),
|
||||
m('dc:language', 'en'),
|
||||
m('meta', {name: 'cover', content: 'cover'}),
|
||||
m('meta', {property: 'dcterms:modified'}, new Date(storyInfo.date_modified*1000).toISOString().replace('.000',''))
|
||||
].concat(subjects(['Fiction', 'Pony']))),
|
||||
m('manifest', [
|
||||
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'}),
|
||||
m('item', {id: 'style', href: 'style.css', 'media-type': 'text/css'}),
|
||||
m('item', {id: 'coverstyle', href: 'coverstyle.css', 'media-type': 'text/css'}),
|
||||
m('item', {id: 'coverpage', href: 'cover.xhtml', 'media-type': 'application/xhtml+xml', properties: 'svg'})
|
||||
].concat(storyInfo.chapters.map((ch) =>
|
||||
m('item', {id: 'chapter_' + ch.id, href: 'chapter_' + ch.id + '.xhtml', 'media-type': 'application/xhtml+xml'})
|
||||
), remotes)),
|
||||
|
||||
m('manifest', [
|
||||
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'}),
|
||||
m('item', {id: 'style', href: 'style.css', 'media-type': 'text/css'}),
|
||||
m('item', {id: 'coverstyle', href: 'coverstyle.css', 'media-type': 'text/css'}),
|
||||
m('item', {id: 'coverpage', href: 'cover.xhtml', 'media-type': 'application/xhtml+xml', properties: 'svg'})
|
||||
].concat(storyInfo.chapters.map((ch) =>
|
||||
m('item', {id: 'chapter_'+ch.id, href: 'chapter_'+ch.id+'.xhtml', 'media-type': 'application/xhtml+xml'})
|
||||
), remotes)),
|
||||
m('spine', {toc: 'ncx'}, [
|
||||
m('itemref', {idref: 'coverpage'}),
|
||||
m('itemref', {idref: 'nav'})
|
||||
].concat(storyInfo.chapters.map((ch) =>
|
||||
m('itemref', {idref: 'chapter_' + ch.id})
|
||||
))),
|
||||
|
||||
m('spine', {toc: 'ncx'}, [
|
||||
m('itemref', {idref: 'coverpage'}),
|
||||
m('itemref', {idref: 'nav'})
|
||||
].concat(storyInfo.chapters.map((ch) =>
|
||||
m('itemref', {idref: 'chapter_'+ch.id})
|
||||
))),
|
||||
false ? m('guide', [
|
||||
|
||||
false? m('guide', [
|
||||
|
||||
]):null
|
||||
])
|
||||
))
|
||||
//console.log(contentOpf)
|
||||
return contentOpf
|
||||
]) : null
|
||||
])
|
||||
))
|
||||
// console.log(contentOpf)
|
||||
return contentOpf
|
||||
}
|
||||
|
||||
|
||||
function navPoints(list) {
|
||||
var arr = []
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
list[i]
|
||||
arr.push(m('navPoint', {id: 'navPoint-'+(i+1), playOrder: i+1}, [
|
||||
m('navLabel', m('text', list[i][0])),
|
||||
m('content', {src: list[i][1]})
|
||||
]))
|
||||
}
|
||||
return arr
|
||||
function navPoints (list) {
|
||||
var arr = []
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
list[i]
|
||||
arr.push(m('navPoint', {id: 'navPoint-' + (i + 1), playOrder: i + 1}, [
|
||||
m('navLabel', m('text', list[i][0])),
|
||||
m('content', {src: list[i][1]})
|
||||
]))
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
function createNcx() {
|
||||
let tocNcx = `<?xml version="1.0" encoding="utf-8" ?>
|
||||
`+pretty.xml(render(
|
||||
m('ncx', {version: '2005-1', xmlns: NS.DAISY}, [
|
||||
m('head', [
|
||||
m('meta', {content: storyInfo.uuid, name: 'dtb:uid'}),
|
||||
m('meta', {content: 0, name: 'dtb:depth'}),
|
||||
m('meta', {content: 0, name: 'dtb:totalPageCount'}),
|
||||
m('meta', {content: 0, name: 'dtb:maxPageNumber'})
|
||||
]),
|
||||
m('docTitle', m('text', storyInfo.title)),
|
||||
m('navMap', navPoints([
|
||||
['Cover', 'cover.xhtml'],
|
||||
['Contents', 'nav.xhtml']
|
||||
].concat(storyInfo.chapters.map((ch) =>
|
||||
[ch.title, 'chapter_'+ch.id+'.xhtml']
|
||||
))))
|
||||
])
|
||||
))
|
||||
//console.log(tocNcx)
|
||||
return tocNcx
|
||||
function createNcx () {
|
||||
let tocNcx = '<?xml version="1.0" encoding="utf-8" ?>\n' + pretty.xml(render(
|
||||
m('ncx', {version: '2005-1', xmlns: NS.DAISY}, [
|
||||
m('head', [
|
||||
m('meta', {content: storyInfo.uuid, name: 'dtb:uid'}),
|
||||
m('meta', {content: 0, name: 'dtb:depth'}),
|
||||
m('meta', {content: 0, name: 'dtb:totalPageCount'}),
|
||||
m('meta', {content: 0, name: 'dtb:maxPageNumber'})
|
||||
]),
|
||||
m('docTitle', m('text', storyInfo.title)),
|
||||
m('navMap', navPoints([
|
||||
['Cover', 'cover.xhtml'],
|
||||
['Contents', 'nav.xhtml']
|
||||
].concat(storyInfo.chapters.map((ch) =>
|
||||
[ch.title, 'chapter_' + ch.id + '.xhtml']
|
||||
))))
|
||||
])
|
||||
))
|
||||
// console.log(tocNcx)
|
||||
return tocNcx
|
||||
}
|
||||
|
||||
|
||||
function createNav() {
|
||||
let navDocument = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE html>
|
||||
`+pretty.xml(render(
|
||||
m('html', {xmlns: NS.XHTML, 'xmlns:epub': NS.OPS, lang: 'en', 'xml:lang': 'en'}, [
|
||||
m('head', [
|
||||
m('meta', {charset: 'utf-8'}),
|
||||
m('link', {rel: 'stylesheet', type: 'text/css', href: 'style.css'}),
|
||||
m('title', 'Contents')
|
||||
]),
|
||||
m('body', [
|
||||
m('nav', {'epub:type': 'toc', id: 'toc'}, [
|
||||
m('h1', 'Contents'),
|
||||
m('ol', [
|
||||
m('li', {hidden: ''}, m('a', {href: 'cover.xhtml'}, 'Cover')),
|
||||
m('li', {hidden: ''}, m('a', {href: 'nav.xhtml'}, 'Contents'))
|
||||
].concat(storyInfo.chapters.map((ch) =>
|
||||
m('li', m('a', {href: 'chapter_'+ch.id+'.xhtml'}, ch.title))
|
||||
)))
|
||||
])
|
||||
])
|
||||
])
|
||||
))
|
||||
//console.log(navDocument)
|
||||
return navDocument
|
||||
function createNav () {
|
||||
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, lang: 'en', 'xml:lang': 'en'}, [
|
||||
m('head', [
|
||||
m('meta', {charset: 'utf-8'}),
|
||||
m('link', {rel: 'stylesheet', type: 'text/css', href: 'style.css'}),
|
||||
m('title', 'Contents')
|
||||
]),
|
||||
m('body', [
|
||||
m('nav', {'epub:type': 'toc', id: 'toc'}, [
|
||||
m('h1', 'Contents'),
|
||||
m('ol', [
|
||||
m('li', {hidden: ''}, m('a', {href: 'cover.xhtml'}, 'Cover')),
|
||||
m('li', {hidden: ''}, m('a', {href: 'nav.xhtml'}, 'Contents'))
|
||||
].concat(storyInfo.chapters.map((ch) =>
|
||||
m('li', m('a', {href: 'chapter_' + ch.id + '.xhtml'}, ch.title))
|
||||
)))
|
||||
])
|
||||
])
|
||||
])
|
||||
))
|
||||
// console.log(navDocument)
|
||||
return navDocument
|
||||
}
|
||||
|
||||
function createCoverPage(w, h) {
|
||||
let coverPage = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE html>
|
||||
`+pretty.xml(render(
|
||||
m('html', {xmlns: NS.XHTML, 'xmlns:epub': NS.OPS}, [
|
||||
m('head', [
|
||||
m('meta', {name: 'viewport', content: 'width='+w+', height='+h}),
|
||||
m('title', 'Cover'),
|
||||
m('link', {rel: 'stylesheet', type: 'text/css', href: 'coverstyle.css'})
|
||||
]),
|
||||
m('body', {'epub:type': 'cover'}, [
|
||||
m('svg', {xmlns: NS.SVG, 'xmlns:xlink': NS.XLINK, version: '1.1', viewBox: '0 0 '+w+' '+h, id: 'cover'},
|
||||
m('image', {width: w, height: h, 'xlink:href': 'Images/cover.jpg'})
|
||||
)
|
||||
])
|
||||
])
|
||||
))
|
||||
//console.log(coverPage)
|
||||
return coverPage
|
||||
function createCoverPage (w, h) {
|
||||
let coverPage = '<?xml version="1.0" encoding="utf-8"?>\n<!DOCTYPE html>\n' + pretty.xml(render(
|
||||
m('html', {xmlns: NS.XHTML, 'xmlns:epub': NS.OPS}, [
|
||||
m('head', [
|
||||
m('meta', {name: 'viewport', content: 'width=' + w + ', height=' + h}),
|
||||
m('title', 'Cover'),
|
||||
m('link', {rel: 'stylesheet', type: 'text/css', href: 'coverstyle.css'})
|
||||
]),
|
||||
m('body', {'epub:type': 'cover'}, [
|
||||
m('svg', {xmlns: NS.SVG, 'xmlns:xlink': NS.XLINK, version: '1.1', viewBox: '0 0 ' + w + ' ' + h, id: 'cover'},
|
||||
m('image', {width: w, height: h, 'xlink:href': 'Images/cover.jpg'})
|
||||
)
|
||||
])
|
||||
])
|
||||
))
|
||||
// console.log(coverPage)
|
||||
return coverPage
|
||||
}
|
||||
|
||||
|
||||
zip.file('style.css', `
|
||||
body {
|
||||
background-color: white;
|
||||
color: black;
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
p {
|
||||
margin-top: 0.0em;
|
||||
margin-bottom: 0.0em;
|
||||
text-indent: 0.0em;
|
||||
margin-top: 0.0em;
|
||||
margin-bottom: 0.0em;
|
||||
text-indent: 0.0em;
|
||||
}
|
||||
p.double {
|
||||
margin-top: 1.0em;
|
||||
margin-top: 1.0em;
|
||||
}
|
||||
p.double2 {
|
||||
margin-top: 1.0em;
|
||||
margin-bottom: 1.0em;
|
||||
margin-top: 1.0em;
|
||||
margin-bottom: 1.0em;
|
||||
}
|
||||
p.indented {
|
||||
text-indent: 1.0em;
|
||||
text-indent: 1.0em;
|
||||
}
|
||||
|
||||
img {
|
||||
height: auto;
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
height: auto;
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 10px 0px;
|
||||
padding: 20px;
|
||||
border: none;
|
||||
border-left: 5px solid rgba(0,0,0,0.2);
|
||||
background: rgba(0,0,0,0.1);
|
||||
margin: 10px 0px;
|
||||
padding: 20px;
|
||||
border: none;
|
||||
border-left: 5px solid rgba(0,0,0,0.2);
|
||||
background: rgba(0,0,0,0.1);
|
||||
}
|
||||
blockquote.left_insert {
|
||||
box-sizing:border-box;
|
||||
-moz-box-sizing:border-box;
|
||||
margin-right:25px;
|
||||
padding: 15px;
|
||||
background-color: #F7F7F7;
|
||||
border: 1px solid #AAA;
|
||||
width: 50%;
|
||||
float:left;
|
||||
box-shadow: 5px 5px 0px #EEE;
|
||||
box-sizing:border-box;
|
||||
-moz-box-sizing:border-box;
|
||||
margin-right:25px;
|
||||
padding: 15px;
|
||||
background-color: #F7F7F7;
|
||||
border: 1px solid #AAA;
|
||||
width: 50%;
|
||||
float:left;
|
||||
box-shadow: 5px 5px 0px #EEE;
|
||||
}
|
||||
blockquote.right_insert {
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
hr {
|
||||
background-color: #ddd;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
color: #ddd;
|
||||
height: 1px;
|
||||
border: 0px;
|
||||
background-color: #ddd;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
color: #ddd;
|
||||
height: 1px;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
#author_notes {
|
||||
clear: both;
|
||||
border: 1px solid;
|
||||
border-radius: 3px;
|
||||
line-height: 1.7em;
|
||||
padding: 16px;
|
||||
margin-top: 1.0em;
|
||||
margin-bottom: 1.0em;
|
||||
clear: both;
|
||||
border: 1px solid;
|
||||
border-radius: 3px;
|
||||
line-height: 1.7em;
|
||||
padding: 16px;
|
||||
margin-top: 1.0em;
|
||||
margin-bottom: 1.0em;
|
||||
}
|
||||
|
||||
#toc [hidden] {
|
||||
display: none;
|
||||
display: none;
|
||||
}
|
||||
`)
|
||||
|
||||
zip.file('coverstyle.css', `
|
||||
@page {padding: 0; margin:0;}
|
||||
html, body {
|
||||
padding:0;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
padding:0;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
#cover {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
`)
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
'use strict'
|
||||
|
||||
var VOID_TAGS = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr',
|
||||
'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track',
|
||||
'wbr', '!doctype']
|
||||
|
||||
function isArray (thing) {
|
||||
return Object.prototype.toString.call(thing) === '[object Array]'
|
||||
}
|
||||
|
@ -25,9 +21,9 @@ function escapeHtml (s, replaceDoubleQuote) {
|
|||
if (typeof (s) !== 'string') {
|
||||
s = s + ''
|
||||
}
|
||||
s = s.replace(/\&/g, '&').replace(/</g, '<').replace(/\>/g, '>')
|
||||
s = s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
if (replaceDoubleQuote) {
|
||||
return s.replace(/\"/g, '"')
|
||||
return s.replace(/"/g, '"')
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
@ -121,7 +117,7 @@ function render (view, options) {
|
|||
return '' + view
|
||||
}
|
||||
var children = createChildrenContent(view)
|
||||
if (!children/* && VOID_TAGS.indexOf(view.tag.toLowerCase()) >= 0*/) {
|
||||
if (!children) {
|
||||
return '<' + view.tag + createAttrString(view, options.escapeAttributeValue) + '/>'
|
||||
}
|
||||
return [
|
||||
|
@ -133,4 +129,4 @@ function render (view, options) {
|
|||
|
||||
render.escapeHtml = escapeHtml
|
||||
|
||||
module.exports = render
|
||||
module.exports = render
|
||||
|
|
|
@ -1,49 +1,40 @@
|
|||
'use strict'
|
||||
|
||||
import webpack from 'webpack'
|
||||
// import webpack from 'webpack'
|
||||
import path from 'path'
|
||||
|
||||
let inProduction = process.env.NODE_ENV === 'production' || process.argv.indexOf('-p') !== -1
|
||||
|
||||
export default {
|
||||
entry: {
|
||||
fimfic2epub: ['./src/main']
|
||||
},
|
||||
output: {
|
||||
path: __dirname + '/',
|
||||
filename: './extension/[name].js',
|
||||
chunkFilename: './build/[id].js'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.js$/, loader: 'babel', exclude: /node_modules/, query: {
|
||||
sourceMaps: inProduction,
|
||||
//presets: ['es2015'],
|
||||
//plugins: ['transform-strict-mode']
|
||||
}
|
||||
}
|
||||
],
|
||||
noParse: [
|
||||
/[\/\\]node_modules[\/\\]tidy-html5[\/\\]tidy\.js$/
|
||||
]
|
||||
},
|
||||
entry: {
|
||||
fimfic2epub: ['./src/main']
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, '/'),
|
||||
filename: './extension/[name].js'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.js$/, loader: 'babel', exclude: /node_modules/, query: {
|
||||
sourceMaps: inProduction,
|
||||
presets: ['es2015'],
|
||||
plugins: ['transform-strict-mode']
|
||||
}
|
||||
}
|
||||
],
|
||||
noParse: [
|
||||
/[\/\\]node_modules[\/\\]tidy-html5[\/\\]tidy\.js$/
|
||||
]
|
||||
},
|
||||
|
||||
resolve: {
|
||||
extensions: ['', '.js', '.json'],
|
||||
root: [__dirname+'/src']
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['', '.js', '.json'],
|
||||
root: [path.join(__dirname, '/src')]
|
||||
},
|
||||
|
||||
plugins: [
|
||||
plugins: [],
|
||||
|
||||
new webpack.ProvidePlugin({
|
||||
// Detect and inject
|
||||
//tidy: 'tidy-html5'
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
|
||||
})
|
||||
],
|
||||
|
||||
devtool: 'inline-source-map',
|
||||
debug: true
|
||||
devtool: 'inline-source-map',
|
||||
debug: true
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue