mirror of
https://github.com/daniel-j/fimfic2epub.git
synced 2024-05-13 08:52:56 +12:00
proper module
This commit is contained in:
parent
daf4c4ec7f
commit
0fbacd0546
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,12 +1,13 @@
|
|||
|
||||
.DS_Store
|
||||
node_modules/
|
||||
extension/fimfic2epub.js
|
||||
extension/eventPage.js
|
||||
extension/*.js.map
|
||||
extension.crx
|
||||
extension.pem
|
||||
extension.xpi
|
||||
extension.zip
|
||||
fimfic2epub.safariextension/
|
||||
fimfic2epub.js
|
||||
fimfic2epub.js.map
|
||||
*.epub
|
||||
|
|
10
README.md
10
README.md
|
@ -15,12 +15,18 @@ Right now the addon is not available in Add-ons for Firefox, but it's fully comp
|
|||
Installation & usage (command line)
|
||||
-------------------
|
||||
|
||||
You can install the tool by running `npm install -g fimfic2epub`. You can then run it with `$ fimfic2epub <story id>`. This will save the EPUB in the current working directory.
|
||||
You can install the tool by running `npm install -g fimfic2epub`. You can then run it with `$ fimfic2epub <story id> <optional filename>`. By default the EPUB will be saved in the current working directory with the filename `Title by Author.epub`. You can set filename to `-` and the epub will be emitted to stdout instead.
|
||||
|
||||
Example:
|
||||
```
|
||||
Download Tag Test by McPoodle
|
||||
Download with automatic filename:
|
||||
$ fimfic2epub 180690
|
||||
|
||||
Download and save to a specified filename:
|
||||
$ fimfic2epub 180690 path/to/file.epub
|
||||
|
||||
Same as above, but use a pipe:
|
||||
$ fimfic2epub 180690 - > path/to/file.epub
|
||||
```
|
||||
|
||||
|
||||
|
|
|
@ -1,11 +1,38 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const FimFic2Epub = require('../fimfic2epub')
|
||||
const fs = require('fs')
|
||||
|
||||
const STORY_ID = process.argv[2]
|
||||
|
||||
const ffc = new FimFic2Epub(STORY_ID)
|
||||
|
||||
ffc.download().then(() => {
|
||||
ffc.saveStory()
|
||||
const outputStdout = process.argv[3] === '-' || process.argv[3] === '/dev/stdout'
|
||||
|
||||
if (outputStdout) {
|
||||
console.log = console.error
|
||||
console.log('Outputting to stdout')
|
||||
}
|
||||
|
||||
ffc.download()
|
||||
.then(() => {
|
||||
let filename = process.argv[3] || ffc.filename
|
||||
let stream
|
||||
|
||||
if (outputStdout) {
|
||||
stream = process.stdout
|
||||
} else {
|
||||
stream = fs.createWriteStream(filename)
|
||||
}
|
||||
ffc.streamFile()
|
||||
.pipe(stream)
|
||||
.on('finish', () => {
|
||||
if (!outputStdout) {
|
||||
console.log('Saved story as ' + filename)
|
||||
}
|
||||
})
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log('Error: ' + (err || 'Unknown error'))
|
||||
process.exit(1)
|
||||
})
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"name": "fimfic2epub",
|
||||
"short_name": "fimfic2epub",
|
||||
"description": "Improved EPUB exporter for Fimfiction",
|
||||
"version": "1.0.9",
|
||||
"version": "1.1.0",
|
||||
|
||||
"icons": {
|
||||
"128": "icon-128.png"
|
||||
|
|
|
@ -34,26 +34,21 @@ webpackConfig.forEach((c) => {
|
|||
debug: false
|
||||
}))
|
||||
c.plugins.push(new webpack.optimize.DedupePlugin())
|
||||
/*
|
||||
c.plugins.push(new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
warnings: false,
|
||||
screw_ie8: true
|
||||
},
|
||||
comments: false,
|
||||
mangle: {
|
||||
screw_ie8: true
|
||||
},
|
||||
screw_ie8: true,
|
||||
sourceMap: false
|
||||
}))
|
||||
*/
|
||||
if (c.uglify) {
|
||||
c.plugins.push(new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
warnings: false,
|
||||
screw_ie8: true
|
||||
},
|
||||
comments: false,
|
||||
mangle: {
|
||||
screw_ie8: true
|
||||
},
|
||||
screw_ie8: true,
|
||||
sourceMap: !!c.devtool
|
||||
}))
|
||||
}
|
||||
}
|
||||
Object.assign({}, c, {
|
||||
cache: {},
|
||||
devtool: inProduction ? null : 'inline-source-map',
|
||||
debug: !inProduction
|
||||
})
|
||||
})
|
||||
|
||||
const wpCompiler = webpack(webpackConfig)
|
||||
|
@ -79,7 +74,17 @@ let lintPipe = lazypipe()
|
|||
.pipe(standard.reporter, 'default', { breakOnError: false })
|
||||
|
||||
// Cleanup task
|
||||
gulp.task('clean', () => del(['extension/fimfic2epub.js', 'extension/eventPage.js']))
|
||||
gulp.task('clean', () => del([
|
||||
'extension/fimfic2epub.js',
|
||||
'extension/eventPage.js',
|
||||
'extension/*.js.map',
|
||||
'fimfic2epub.js',
|
||||
'fimfic2epub.js.map',
|
||||
'extension.zip',
|
||||
'extension.xpi',
|
||||
'extension.crx',
|
||||
'fimfic2epub.safariextension/'
|
||||
]))
|
||||
|
||||
// Main tasks
|
||||
gulp.task('webpack', webpackTask)
|
||||
|
@ -90,7 +95,7 @@ gulp.task('watch:webpack', () => {
|
|||
})
|
||||
|
||||
gulp.task('lint', () => {
|
||||
return gulp.src(['gulpfile.babel.js', 'webpack.config.babel.js', 'src/**/*.js']).pipe(lintPipe())
|
||||
return gulp.src(['gulpfile.babel.js', 'webpack.config.babel.js', 'src/**/*.js', 'bin/fimfic2epub']).pipe(lintPipe())
|
||||
})
|
||||
gulp.task('watch:lint', () => {
|
||||
return watch(['src/**/*.js'], watchOpts, function (file) {
|
||||
|
@ -147,7 +152,7 @@ gulp.task('pack:chrome', (done) => {
|
|||
})
|
||||
|
||||
gulp.task('pack:safari', (done) => {
|
||||
exec('cp -r extension/ fimfic2epub.safariextension', [], (error, stdout, stderr) => {
|
||||
exec('rm -rf fimfic2epub.safariextension/; cp -r extension/ fimfic2epub.safariextension', [], (error, stdout, stderr) => {
|
||||
// gutil.log('[pack:chrome]', stdout)
|
||||
if (error || stderr) {
|
||||
done(new gutil.PluginError('pack:safari', stderr, {showStack: false}))
|
||||
|
|
17
package.json
17
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "fimfic2epub",
|
||||
"version": "1.0.9",
|
||||
"version": "1.1.0",
|
||||
"description": "Tool to generate EPUB ebooks from fimfiction stories",
|
||||
"author": "djazz",
|
||||
"scripts": {
|
||||
|
@ -10,13 +10,13 @@
|
|||
"fimfic2epub": "./bin/fimfic2epub"
|
||||
},
|
||||
"main": "fimfic2epub.js",
|
||||
"engines": {
|
||||
"node": ">=0.6.0"
|
||||
},
|
||||
|
||||
"files": [
|
||||
"fimfic2epub.js",
|
||||
"fimfic2epub.js.map",
|
||||
"bin/"
|
||||
],
|
||||
|
||||
"dependencies": {
|
||||
"detect-node": "^2.0.3",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
|
@ -26,17 +26,19 @@
|
|||
"mithril": "^0.2.5",
|
||||
"pretty-data": "^0.40.0",
|
||||
"request": "^2.74.0",
|
||||
"sanitize-filename": "^1.6.0",
|
||||
"tidy-html5": "^0.1.1",
|
||||
"zero-fill": "^2.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"file-saver": "^1.3.2",
|
||||
"babel-register": "^6.11.6",
|
||||
"babel-preset-node6": "^11.0.0",
|
||||
"babel-core": "^6.13.2",
|
||||
"babel-loader": "^6.2.4",
|
||||
"babel-preset-es2015": "^6.13.2",
|
||||
"babel-preset-node6": "^11.0.0",
|
||||
"babel-register": "^6.11.6",
|
||||
"del": "^2.2.2",
|
||||
"exports-loader": "^0.6.3",
|
||||
"file-saver": "^1.3.2",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-filter": "^4.0.0",
|
||||
"gulp-json-editor": "^2.2.1",
|
||||
|
@ -53,6 +55,7 @@
|
|||
"webpack": "^2.1.0-beta.13",
|
||||
"webpack-node-externals": "^1.3.3"
|
||||
},
|
||||
|
||||
"standard": {
|
||||
"env": {
|
||||
"browser": true
|
||||
|
|
|
@ -3,6 +3,7 @@ import JSZip from 'jszip'
|
|||
import escapeStringRegexp from 'escape-string-regexp'
|
||||
import zeroFill from 'zero-fill'
|
||||
import { XmlEntities } from 'html-entities'
|
||||
import sanitize from 'sanitize-filename'
|
||||
|
||||
import isNode from 'detect-node'
|
||||
|
||||
|
@ -16,12 +17,6 @@ import { mimeMap, containerXml } from './constants'
|
|||
|
||||
const entities = new XmlEntities()
|
||||
|
||||
function blobToDataURL (blob, callback) {
|
||||
let a = new FileReader()
|
||||
a.onloadend = function (e) { callback(a.result) }
|
||||
a.readAsDataURL(blob)
|
||||
}
|
||||
|
||||
module.exports = class FimFic2Epub {
|
||||
|
||||
constructor (storyId) {
|
||||
|
@ -32,7 +27,7 @@ module.exports = class FimFic2Epub {
|
|||
this.remoteResources = new Map()
|
||||
this.storyInfo = null
|
||||
this.isDownloading = false
|
||||
this.cachedBlob = null
|
||||
this.cachedFile = null
|
||||
this.hasCoverImage = false
|
||||
this.includeTitlePage = true
|
||||
this.categories = []
|
||||
|
@ -42,10 +37,10 @@ module.exports = class FimFic2Epub {
|
|||
download () {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.isDownloading) {
|
||||
reject()
|
||||
reject('Already downloading')
|
||||
return
|
||||
}
|
||||
if (this.cachedBlob) {
|
||||
if (this.cachedFile) {
|
||||
resolve()
|
||||
return
|
||||
}
|
||||
|
@ -79,6 +74,8 @@ module.exports = class FimFic2Epub {
|
|||
this.storyInfo.chapters = this.storyInfo.chapters || []
|
||||
this.storyInfo.uuid = 'urn:fimfiction:' + this.storyInfo.id
|
||||
|
||||
this.filename = sanitize(this.storyInfo.title + ' by ' + this.storyInfo.author.name + '.epub')
|
||||
|
||||
this.zip.file('Styles/style.css', styleCss)
|
||||
this.zip.file('Styles/coverstyle.css', coverstyleCss)
|
||||
if (this.includeTitlePage) {
|
||||
|
@ -245,26 +242,8 @@ module.exports = class FimFic2Epub {
|
|||
|
||||
this.zip.file('content.opf', template.createOpf(this))
|
||||
|
||||
console.log('Packaging epub...')
|
||||
|
||||
if (!isNode) {
|
||||
this.zip
|
||||
.generateAsync({
|
||||
type: 'blob',
|
||||
mimeType: 'application/epub+zip',
|
||||
compression: 'DEFLATE',
|
||||
compressionOptions: {level: 9}
|
||||
})
|
||||
.then((blob) => {
|
||||
this.cachedBlob = blob
|
||||
this.isDownloading = false
|
||||
resolve()
|
||||
})
|
||||
} else {
|
||||
this.cachedBlob = true
|
||||
this.isDownloading = false
|
||||
resolve()
|
||||
}
|
||||
this.isDownloading = false
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -373,47 +352,35 @@ module.exports = class FimFic2Epub {
|
|||
}
|
||||
}
|
||||
|
||||
saveStory () {
|
||||
let filename = this.storyInfo.title + ' by ' + this.storyInfo.author.name + '.epub'
|
||||
|
||||
console.log('Saving epub...')
|
||||
|
||||
if (isNode) {
|
||||
const fs = require('fs')
|
||||
/*this.zip.generateAsync({
|
||||
type: 'nodebuffer',
|
||||
mimeType: 'application/epub+zip',
|
||||
compression: 'DEFLATE',
|
||||
compressionOptions: {level: 9}
|
||||
}).then((epub) => {
|
||||
console.log(epub)
|
||||
})*/
|
||||
|
||||
// for node, resolve a Buffer, in browser resolve a Blob
|
||||
getFile () {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.cachedFile) {
|
||||
resolve(this.cachedFile, this.filename)
|
||||
return
|
||||
}
|
||||
this.zip
|
||||
.generateNodeStream({
|
||||
type: 'nodebuffer',
|
||||
streamFiles: true,
|
||||
.generateAsync({
|
||||
type: isNode ? 'nodebuffer' : 'blob',
|
||||
mimeType: 'application/epub+zip',
|
||||
compression: 'DEFLATE',
|
||||
compressionOptions: {level: 9}
|
||||
}).then((file) => {
|
||||
this.cachedFile = file
|
||||
resolve(file)
|
||||
})
|
||||
.pipe(fs.createWriteStream(filename))
|
||||
.on('finish', () => {
|
||||
console.log('Saved epub as', filename)
|
||||
})
|
||||
.on('error', (err) => {
|
||||
throw err
|
||||
})
|
||||
return
|
||||
}
|
||||
if (typeof safari !== 'undefined') {
|
||||
blobToDataURL(this.cachedBlob, (dataurl) => {
|
||||
document.location.href = dataurl
|
||||
alert('Rename downloaded file to .epub')
|
||||
})
|
||||
} else {
|
||||
const saveAs = require('file-saver')
|
||||
saveAs(this.cachedBlob, filename)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// example usage: .pipe(fs.createWriteStream(filename))
|
||||
streamFile () {
|
||||
return this.zip
|
||||
.generateNodeStream({
|
||||
type: 'nodebuffer',
|
||||
streamFiles: true,
|
||||
mimeType: 'application/epub+zip',
|
||||
compression: 'DEFLATE',
|
||||
compressionOptions: {level: 9}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
19
src/main.js
19
src/main.js
|
@ -1,5 +1,12 @@
|
|||
|
||||
import FimFic2Epub from './FimFic2Epub'
|
||||
import { saveAs } from 'file-saver'
|
||||
|
||||
function blobToDataURL (blob, callback) {
|
||||
let a = new FileReader()
|
||||
a.onloadend = function (e) { callback(a.result) }
|
||||
a.readAsDataURL(blob)
|
||||
}
|
||||
|
||||
const STORY_ID = document.location.pathname.match(/^\/story\/(\d*)/)[1]
|
||||
|
||||
|
@ -11,7 +18,17 @@ if (epubButton) {
|
|||
epubButton.addEventListener('click', function (e) {
|
||||
e.preventDefault()
|
||||
ffc.download().then(() => {
|
||||
ffc.saveStory()
|
||||
ffc.getFile().then((file) => {
|
||||
console.log('Saving file...')
|
||||
if (typeof safari !== 'undefined') {
|
||||
blobToDataURL(file, (dataurl) => {
|
||||
document.location.href = dataurl
|
||||
alert('Add .epub to the filename of the downloaded file')
|
||||
})
|
||||
} else {
|
||||
saveAs(file, ffc.filename)
|
||||
}
|
||||
})
|
||||
})
|
||||
}, false)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
let inProduction = process.env.NODE_ENV === 'production' || process.argv.indexOf('-p') !== -1
|
||||
|
||||
const bundleExtensionConfig = {
|
||||
entry: {
|
||||
|
@ -17,13 +17,12 @@ const bundleExtensionConfig = {
|
|||
|
||||
module: {
|
||||
loaders: [
|
||||
/*
|
||||
{
|
||||
test: /\.js$/, loader: 'babel', exclude: /node_modules/, query: {
|
||||
sourceMaps: inProduction
|
||||
sourceMaps: true,
|
||||
presets: ['es2015']
|
||||
}
|
||||
},
|
||||
*/
|
||||
{
|
||||
test: /\.styl$/,
|
||||
loader: 'raw-loader!stylus-loader'
|
||||
|
@ -45,8 +44,9 @@ const bundleExtensionConfig = {
|
|||
externals: ['request', 'fs', 'tidy-html5', 'image-size'],
|
||||
|
||||
plugins: [],
|
||||
devtool: 'inline-source-map',
|
||||
debug: true
|
||||
devtool: 'source-map',
|
||||
debug: true,
|
||||
uglify: inProduction
|
||||
}
|
||||
|
||||
const bundleNpmModuleConfig = {
|
||||
|
@ -62,13 +62,12 @@ const bundleNpmModuleConfig = {
|
|||
|
||||
module: {
|
||||
loaders: [
|
||||
/*
|
||||
{
|
||||
test: /\.js$/, loader: 'babel', exclude: /node_modules/, query: {
|
||||
sourceMaps: inProduction
|
||||
sourceMaps: !inProduction,
|
||||
presets: ['es2015']
|
||||
}
|
||||
},
|
||||
*/
|
||||
{
|
||||
test: /\.styl$/,
|
||||
loader: 'raw-loader!stylus-loader'
|
||||
|
@ -90,8 +89,9 @@ const bundleNpmModuleConfig = {
|
|||
externals: [nodeExternals(), 'exports?tidy_html5!tidy-html5'],
|
||||
|
||||
plugins: [],
|
||||
devtool: 'inline-source-map',
|
||||
debug: true
|
||||
devtool: 'source-map',
|
||||
debug: true,
|
||||
uglify: inProduction
|
||||
}
|
||||
|
||||
export default [bundleExtensionConfig, bundleNpmModuleConfig]
|
||||
|
|
Loading…
Reference in a new issue