wp-epub-gen 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{dist → build}/downloadImage.d.ts +0 -0
- package/{dist → build}/downloadImage.js +0 -0
- package/build/downloadImage.js.map +1 -0
- package/{dist → build}/errors.d.ts +0 -0
- package/{dist → build}/errors.js +0 -0
- package/build/errors.js.map +1 -0
- package/{dist → build}/generateTempFile.d.ts +0 -0
- package/{dist → build}/generateTempFile.js +0 -0
- package/build/generateTempFile.js.map +1 -0
- package/{dist → build}/index.d.ts +0 -0
- package/{dist → build}/index.js +0 -0
- package/build/index.js.map +1 -0
- package/{dist → build}/makeCover.d.ts +0 -0
- package/{dist → build}/makeCover.js +0 -0
- package/build/makeCover.js.map +1 -0
- package/{dist → build}/parseContent.d.ts +0 -0
- package/{dist → build}/parseContent.js +0 -0
- package/build/parseContent.js.map +1 -0
- package/{dist → build}/render.d.ts +0 -0
- package/{dist → build}/render.js +0 -0
- package/build/render.js.map +1 -0
- package/{dist → build}/utils.d.ts +0 -0
- package/{dist → build}/utils.js +0 -0
- package/build/utils.js.map +1 -0
- package/cpi.epub +0 -0
- package/package.json +17 -21
- package/templates/epub3/content.opf.ejs +19 -22
- package/test.epub +0 -0
- package/tsconfig.json +1 -1
- package/src/downloadImage.ts +0 -83
- package/src/errors.ts +0 -11
- package/src/generateTempFile.ts +0 -144
- package/src/index.ts +0 -152
- package/src/makeCover.ts +0 -52
- package/src/parseContent.ts +0 -351
- package/src/render.ts +0 -84
- package/src/types.d.ts +0 -79
- package/src/utils.ts +0 -39
- package/test/basic.test.js +0 -28
- package/test/child-page-image.test.js +0 -21
- package/test/data/1.json +0 -21
- package/test/tt.js +0 -16
- package/webpack.config.js +0 -75
package/src/index.ts
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* index.ts
|
|
3
|
-
* @author: oldj
|
|
4
|
-
* @homepage: https://oldj.net
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import * as mime from 'mime'
|
|
8
|
-
import * as os from 'os'
|
|
9
|
-
import * as path from 'path'
|
|
10
|
-
import { v4 as uuidv4 } from 'uuid'
|
|
11
|
-
import { errors } from './errors'
|
|
12
|
-
import parseContent from './parseContent'
|
|
13
|
-
import { render } from './render'
|
|
14
|
-
import { IEpubData, IEpubGenOptions, IOut } from './types'
|
|
15
|
-
|
|
16
|
-
const baseDir = path.dirname(__dirname)
|
|
17
|
-
|
|
18
|
-
function result(success: boolean, message?: string, options?: IEpubGenOptions): IOut {
|
|
19
|
-
if (options && options.verbose) {
|
|
20
|
-
if (!success) {
|
|
21
|
-
console.error(new Error(message))
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
let out: IOut = {
|
|
26
|
-
success,
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (typeof message === 'string') {
|
|
30
|
-
out.message = message
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (options) {
|
|
34
|
-
out.options = options
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return out
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function check(options: IEpubGenOptions): IOut {
|
|
41
|
-
if (!options.output) {
|
|
42
|
-
return result(false, errors.no_output_path, options)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (!options.title) {
|
|
46
|
-
return result(false, errors.no_title, options)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (!options.content) {
|
|
50
|
-
return result(false, errors.no_content, options)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return result(true, undefined, options)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function parseOptions(options: IEpubGenOptions): IEpubData {
|
|
57
|
-
let tmpDir = options.tmpDir || os.tmpdir()
|
|
58
|
-
let id = uuidv4()
|
|
59
|
-
|
|
60
|
-
let data: IEpubData = {
|
|
61
|
-
description: options.title,
|
|
62
|
-
publisher: 'anonymous',
|
|
63
|
-
author: ['anonymous'],
|
|
64
|
-
tocTitle: 'Table Of Contents',
|
|
65
|
-
appendChapterTitles: true,
|
|
66
|
-
date: new Date().toISOString(),
|
|
67
|
-
lang: 'en',
|
|
68
|
-
fonts: [],
|
|
69
|
-
version: 3,
|
|
70
|
-
verbose: true,
|
|
71
|
-
timeoutSeconds: 15 * 60, // 15 min
|
|
72
|
-
tocAutoNumber: false,
|
|
73
|
-
|
|
74
|
-
...options,
|
|
75
|
-
|
|
76
|
-
id,
|
|
77
|
-
tmpDir,
|
|
78
|
-
dir: path.resolve(tmpDir, id),
|
|
79
|
-
baseDir,
|
|
80
|
-
docHeader: '',
|
|
81
|
-
images: [],
|
|
82
|
-
content: [],
|
|
83
|
-
log: (msg) => options.verbose && console.log(msg),
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (data.version === 2) {
|
|
87
|
-
data.docHeader = `<?xml version="1.0" encoding="UTF-8"?>
|
|
88
|
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
|
89
|
-
<html xmlns="http://www.w3.org/1999/xhtml" lang="#{self.options.lang}">
|
|
90
|
-
`
|
|
91
|
-
} else {
|
|
92
|
-
data.docHeader = `<?xml version="1.0" encoding="UTF-8"?>
|
|
93
|
-
<!DOCTYPE html>
|
|
94
|
-
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" lang="#{self.options.lang}">
|
|
95
|
-
`
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (Array.isArray(data.author) && data.author.length === 0) {
|
|
99
|
-
data.author = ['anonymous']
|
|
100
|
-
}
|
|
101
|
-
if (typeof data.author === 'string') {
|
|
102
|
-
data.author = [data.author]
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
data.content = options.content.map((content, index) => parseContent(content, index, data))
|
|
106
|
-
|
|
107
|
-
if (data.cover) {
|
|
108
|
-
data._coverMediaType = mime.getType(data.cover) || ''
|
|
109
|
-
data._coverExtension = mime.getExtension(data._coverMediaType) || ''
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return data
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export async function epubGen(options: IEpubGenOptions, output?: string): Promise<IOut> {
|
|
116
|
-
options = { ...options }
|
|
117
|
-
if (output) {
|
|
118
|
-
options.output = output
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
let o = check(options)
|
|
122
|
-
let verbose = options.verbose !== false
|
|
123
|
-
if (!o.success) {
|
|
124
|
-
if (verbose) console.error(o.message)
|
|
125
|
-
return o
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
let t: any
|
|
129
|
-
try {
|
|
130
|
-
let data = parseOptions(options)
|
|
131
|
-
let timeoutSeconds: number = data.timeoutSeconds || 0
|
|
132
|
-
|
|
133
|
-
if (timeoutSeconds > 0) {
|
|
134
|
-
if (verbose) console.log(`TIMEOUT: ${timeoutSeconds}s`)
|
|
135
|
-
t = setTimeout(() => {
|
|
136
|
-
throw new Error('timeout!')
|
|
137
|
-
}, timeoutSeconds * 1000)
|
|
138
|
-
} else {
|
|
139
|
-
if (verbose) console.log(`TIMEOUT: N/A`)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
await render(data)
|
|
143
|
-
return result(true, undefined, data)
|
|
144
|
-
} catch (e) {
|
|
145
|
-
if (verbose) console.error(e)
|
|
146
|
-
return result(false, e.message, options)
|
|
147
|
-
} finally {
|
|
148
|
-
clearTimeout(t)
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export const gen = epubGen
|
package/src/makeCover.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* makeCover
|
|
3
|
-
* @author: oldj
|
|
4
|
-
* @homepage: https://oldj.net
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import * as fs from 'fs-extra'
|
|
8
|
-
import * as path from 'path'
|
|
9
|
-
import * as request from 'superagent'
|
|
10
|
-
import { IEpubData } from './types'
|
|
11
|
-
import { USER_AGENT } from './utils'
|
|
12
|
-
|
|
13
|
-
export default async function makeCover(data: IEpubData): Promise<void> {
|
|
14
|
-
let { cover, _coverExtension, log } = data
|
|
15
|
-
if (!cover) return
|
|
16
|
-
|
|
17
|
-
let destPath = path.join(data.dir, 'OEBPS', `cover.${_coverExtension}`)
|
|
18
|
-
let writeStream: any = null
|
|
19
|
-
|
|
20
|
-
if (cover.startsWith('http')) {
|
|
21
|
-
writeStream = request.get(cover).set({ 'User-Agent': USER_AGENT })
|
|
22
|
-
writeStream.pipe(fs.createWriteStream(destPath))
|
|
23
|
-
} else {
|
|
24
|
-
if (!fs.existsSync(cover)) return
|
|
25
|
-
log('local cover image: ' + cover)
|
|
26
|
-
|
|
27
|
-
writeStream = fs.createReadStream(cover)
|
|
28
|
-
writeStream.pipe(fs.createWriteStream(destPath))
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return new Promise((resolve) => {
|
|
32
|
-
writeStream.on('end', () => {
|
|
33
|
-
log('[Success] cover image saved.')
|
|
34
|
-
resolve()
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
writeStream.on('error', (e: any) => {
|
|
38
|
-
log('[Error] cover image error: ' + e.message)
|
|
39
|
-
log('destPath: ' + destPath)
|
|
40
|
-
if (fs.existsSync(destPath)) {
|
|
41
|
-
try {
|
|
42
|
-
fs.unlinkSync(destPath)
|
|
43
|
-
log('destPath removed.')
|
|
44
|
-
} catch (e) {
|
|
45
|
-
log('[Error] remove cover image error: ' + e.message)
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
resolve(e)
|
|
49
|
-
// throw new Error('[Fail] cover image save fail!')
|
|
50
|
-
})
|
|
51
|
-
})
|
|
52
|
-
}
|
package/src/parseContent.ts
DELETED
|
@@ -1,351 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* parseContent
|
|
3
|
-
* @author: oldj
|
|
4
|
-
* @homepage: https://oldj.net
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import * as cheerio from 'cheerio'
|
|
8
|
-
import { remove as removeDiacritics } from 'diacritics'
|
|
9
|
-
import * as mime from 'mime'
|
|
10
|
-
import * as path from 'path'
|
|
11
|
-
import * as uslug from 'uslug'
|
|
12
|
-
import { v4 as uuidv4 } from 'uuid'
|
|
13
|
-
import { IChapter, IChapterData, IEpubData, IEpubImage } from './types'
|
|
14
|
-
|
|
15
|
-
export default function parseContent(
|
|
16
|
-
content: IChapter,
|
|
17
|
-
index: number | string,
|
|
18
|
-
epubConfigs: IEpubData,
|
|
19
|
-
): IChapterData {
|
|
20
|
-
let chapter: IChapterData = { ...content } as IChapterData
|
|
21
|
-
|
|
22
|
-
if (!chapter.filename) {
|
|
23
|
-
let titleSlug = uslug(removeDiacritics(chapter.title || 'no title'))
|
|
24
|
-
titleSlug = titleSlug.replace(/[\/\\]/g, '_')
|
|
25
|
-
chapter.href = `${index}_${titleSlug}.xhtml`
|
|
26
|
-
chapter.filePath = path.join(epubConfigs.dir, 'OEBPS', chapter.href)
|
|
27
|
-
} else {
|
|
28
|
-
let is_xhtml = chapter.filename.endsWith('.xhtml')
|
|
29
|
-
chapter.href = is_xhtml ? chapter.filename : `${chapter.filename}.xhtml`
|
|
30
|
-
if (is_xhtml) {
|
|
31
|
-
chapter.filePath = path.join(epubConfigs.dir, 'OEBPS', chapter.filename)
|
|
32
|
-
} else {
|
|
33
|
-
chapter.filePath = path.join(epubConfigs.dir, 'OEBPS', `${chapter.filename}.xhtml`)
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
chapter.id = `item_${index}`
|
|
38
|
-
chapter.dir = path.dirname(chapter.filePath)
|
|
39
|
-
chapter.excludeFromToc = chapter.excludeFromToc || false
|
|
40
|
-
chapter.beforeToc = chapter.beforeToc || false
|
|
41
|
-
|
|
42
|
-
// fix author array
|
|
43
|
-
if (chapter.author && typeof chapter.author === 'string') {
|
|
44
|
-
chapter.author = [chapter.author]
|
|
45
|
-
} else if (!chapter.author || !Array.isArray(chapter.author)) {
|
|
46
|
-
chapter.author = []
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
let allowedAttributes = [
|
|
50
|
-
'content',
|
|
51
|
-
'alt',
|
|
52
|
-
'id',
|
|
53
|
-
'title',
|
|
54
|
-
'src',
|
|
55
|
-
'href',
|
|
56
|
-
'about',
|
|
57
|
-
'accesskey',
|
|
58
|
-
'aria-activedescendant',
|
|
59
|
-
'aria-atomic',
|
|
60
|
-
'aria-autocomplete',
|
|
61
|
-
'aria-busy',
|
|
62
|
-
'aria-checked',
|
|
63
|
-
'aria-controls',
|
|
64
|
-
'aria-describedat',
|
|
65
|
-
'aria-describedby',
|
|
66
|
-
'aria-disabled',
|
|
67
|
-
'aria-dropeffect',
|
|
68
|
-
'aria-expanded',
|
|
69
|
-
'aria-flowto',
|
|
70
|
-
'aria-grabbed',
|
|
71
|
-
'aria-haspopup',
|
|
72
|
-
'aria-hidden',
|
|
73
|
-
'aria-invalid',
|
|
74
|
-
'aria-label',
|
|
75
|
-
'aria-labelledby',
|
|
76
|
-
'aria-level',
|
|
77
|
-
'aria-live',
|
|
78
|
-
'aria-multiline',
|
|
79
|
-
'aria-multiselectable',
|
|
80
|
-
'aria-orientation',
|
|
81
|
-
'aria-owns',
|
|
82
|
-
'aria-posinset',
|
|
83
|
-
'aria-pressed',
|
|
84
|
-
'aria-readonly',
|
|
85
|
-
'aria-relevant',
|
|
86
|
-
'aria-required',
|
|
87
|
-
'aria-selected',
|
|
88
|
-
'aria-setsize',
|
|
89
|
-
'aria-sort',
|
|
90
|
-
'aria-valuemax',
|
|
91
|
-
'aria-valuemin',
|
|
92
|
-
'aria-valuenow',
|
|
93
|
-
'aria-valuetext',
|
|
94
|
-
'class',
|
|
95
|
-
'content',
|
|
96
|
-
'contenteditable',
|
|
97
|
-
'contextmenu',
|
|
98
|
-
'datatype',
|
|
99
|
-
'dir',
|
|
100
|
-
'draggable',
|
|
101
|
-
'dropzone',
|
|
102
|
-
'hidden',
|
|
103
|
-
'hreflang',
|
|
104
|
-
'id',
|
|
105
|
-
'inlist',
|
|
106
|
-
'itemid',
|
|
107
|
-
'itemref',
|
|
108
|
-
'itemscope',
|
|
109
|
-
'itemtype',
|
|
110
|
-
'lang',
|
|
111
|
-
'media',
|
|
112
|
-
'ns1:type',
|
|
113
|
-
'ns2:alphabet',
|
|
114
|
-
'ns2:ph',
|
|
115
|
-
'onabort',
|
|
116
|
-
'onblur',
|
|
117
|
-
'oncanplay',
|
|
118
|
-
'oncanplaythrough',
|
|
119
|
-
'onchange',
|
|
120
|
-
'onclick',
|
|
121
|
-
'oncontextmenu',
|
|
122
|
-
'ondblclick',
|
|
123
|
-
'ondrag',
|
|
124
|
-
'ondragend',
|
|
125
|
-
'ondragenter',
|
|
126
|
-
'ondragleave',
|
|
127
|
-
'ondragover',
|
|
128
|
-
'ondragstart',
|
|
129
|
-
'ondrop',
|
|
130
|
-
'ondurationchange',
|
|
131
|
-
'onemptied',
|
|
132
|
-
'onended',
|
|
133
|
-
'onerror',
|
|
134
|
-
'onfocus',
|
|
135
|
-
'oninput',
|
|
136
|
-
'oninvalid',
|
|
137
|
-
'onkeydown',
|
|
138
|
-
'onkeypress',
|
|
139
|
-
'onkeyup',
|
|
140
|
-
'onload',
|
|
141
|
-
'onloadeddata',
|
|
142
|
-
'onloadedmetadata',
|
|
143
|
-
'onloadstart',
|
|
144
|
-
'onmousedown',
|
|
145
|
-
'onmousemove',
|
|
146
|
-
'onmouseout',
|
|
147
|
-
'onmouseover',
|
|
148
|
-
'onmouseup',
|
|
149
|
-
'onmousewheel',
|
|
150
|
-
'onpause',
|
|
151
|
-
'onplay',
|
|
152
|
-
'onplaying',
|
|
153
|
-
'onprogress',
|
|
154
|
-
'onratechange',
|
|
155
|
-
'onreadystatechange',
|
|
156
|
-
'onreset',
|
|
157
|
-
'onscroll',
|
|
158
|
-
'onseeked',
|
|
159
|
-
'onseeking',
|
|
160
|
-
'onselect',
|
|
161
|
-
'onshow',
|
|
162
|
-
'onstalled',
|
|
163
|
-
'onsubmit',
|
|
164
|
-
'onsuspend',
|
|
165
|
-
'ontimeupdate',
|
|
166
|
-
'onvolumechange',
|
|
167
|
-
'onwaiting',
|
|
168
|
-
'prefix',
|
|
169
|
-
'property',
|
|
170
|
-
'rel',
|
|
171
|
-
'resource',
|
|
172
|
-
'rev',
|
|
173
|
-
'role',
|
|
174
|
-
'spellcheck',
|
|
175
|
-
'style',
|
|
176
|
-
'tabindex',
|
|
177
|
-
'target',
|
|
178
|
-
'title',
|
|
179
|
-
'type',
|
|
180
|
-
'typeof',
|
|
181
|
-
'vocab',
|
|
182
|
-
'xml:base',
|
|
183
|
-
'xml:lang',
|
|
184
|
-
'xml:space',
|
|
185
|
-
'colspan',
|
|
186
|
-
'rowspan',
|
|
187
|
-
'epub:type',
|
|
188
|
-
'epub:prefix',
|
|
189
|
-
]
|
|
190
|
-
let allowedXhtml11Tags = [
|
|
191
|
-
'div',
|
|
192
|
-
'p',
|
|
193
|
-
'h1',
|
|
194
|
-
'h2',
|
|
195
|
-
'h3',
|
|
196
|
-
'h4',
|
|
197
|
-
'h5',
|
|
198
|
-
'h6',
|
|
199
|
-
'ul',
|
|
200
|
-
'ol',
|
|
201
|
-
'li',
|
|
202
|
-
'dl',
|
|
203
|
-
'dt',
|
|
204
|
-
'dd',
|
|
205
|
-
'address',
|
|
206
|
-
'hr',
|
|
207
|
-
'pre',
|
|
208
|
-
'blockquote',
|
|
209
|
-
'center',
|
|
210
|
-
'ins',
|
|
211
|
-
'del',
|
|
212
|
-
'a',
|
|
213
|
-
'span',
|
|
214
|
-
'bdo',
|
|
215
|
-
'br',
|
|
216
|
-
'em',
|
|
217
|
-
'strong',
|
|
218
|
-
'dfn',
|
|
219
|
-
'code',
|
|
220
|
-
'samp',
|
|
221
|
-
'kbd',
|
|
222
|
-
'bar',
|
|
223
|
-
'cite',
|
|
224
|
-
'abbr',
|
|
225
|
-
'acronym',
|
|
226
|
-
'q',
|
|
227
|
-
'sub',
|
|
228
|
-
'sup',
|
|
229
|
-
'tt',
|
|
230
|
-
'i',
|
|
231
|
-
'b',
|
|
232
|
-
'big',
|
|
233
|
-
'small',
|
|
234
|
-
'u',
|
|
235
|
-
's',
|
|
236
|
-
'strike',
|
|
237
|
-
'basefont',
|
|
238
|
-
'font',
|
|
239
|
-
'object',
|
|
240
|
-
'param',
|
|
241
|
-
'img',
|
|
242
|
-
'table',
|
|
243
|
-
'caption',
|
|
244
|
-
'colgroup',
|
|
245
|
-
'col',
|
|
246
|
-
'thead',
|
|
247
|
-
'tfoot',
|
|
248
|
-
'tbody',
|
|
249
|
-
'tr',
|
|
250
|
-
'th',
|
|
251
|
-
'td',
|
|
252
|
-
'embed',
|
|
253
|
-
'applet',
|
|
254
|
-
'iframe',
|
|
255
|
-
'img',
|
|
256
|
-
'map',
|
|
257
|
-
'noscript',
|
|
258
|
-
'ns:svg',
|
|
259
|
-
'object',
|
|
260
|
-
'script',
|
|
261
|
-
'table',
|
|
262
|
-
'tt',
|
|
263
|
-
'var',
|
|
264
|
-
]
|
|
265
|
-
|
|
266
|
-
let $ = cheerio.load(chapter.data, {
|
|
267
|
-
lowerCaseTags: true,
|
|
268
|
-
recognizeSelfClosing: true,
|
|
269
|
-
})
|
|
270
|
-
|
|
271
|
-
// only body innerHTML is allowed
|
|
272
|
-
let body = $('body')
|
|
273
|
-
if (body.length) {
|
|
274
|
-
let html = body.html()
|
|
275
|
-
if (html) {
|
|
276
|
-
$ = cheerio.load(html, {
|
|
277
|
-
lowerCaseTags: true,
|
|
278
|
-
recognizeSelfClosing: true,
|
|
279
|
-
})
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
$($('*').get().reverse()).each(function (elemIndex, elem) {
|
|
284
|
-
// @ts-ignore
|
|
285
|
-
let attrs = elem.attribs
|
|
286
|
-
// @ts-ignore
|
|
287
|
-
let that: CheerioElement = this
|
|
288
|
-
let tags = ['img', 'br', 'hr']
|
|
289
|
-
if (tags.includes(that.name)) {
|
|
290
|
-
if (that.name === 'img' && !$(that).attr('alt')) {
|
|
291
|
-
$(that).attr('alt', 'image-placeholder')
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
Object.entries(attrs).map(([k, v]) => {
|
|
296
|
-
if (allowedAttributes.includes(k)) {
|
|
297
|
-
if (k === 'type' && that.name !== 'script') {
|
|
298
|
-
$(that).removeAttr(k)
|
|
299
|
-
}
|
|
300
|
-
} else {
|
|
301
|
-
$(that).removeAttr(k)
|
|
302
|
-
}
|
|
303
|
-
})
|
|
304
|
-
|
|
305
|
-
if (epubConfigs.version === 2) {
|
|
306
|
-
if (!allowedXhtml11Tags.includes(that.name)) {
|
|
307
|
-
if (epubConfigs.verbose) {
|
|
308
|
-
console.log(
|
|
309
|
-
'Warning (content[' + index + ']):',
|
|
310
|
-
that.name,
|
|
311
|
-
"tag isn't allowed on EPUB 2/XHTML 1.1 DTD.",
|
|
312
|
-
)
|
|
313
|
-
}
|
|
314
|
-
let child = $(that).html()
|
|
315
|
-
$(that).replaceWith($('<div>' + child + '</div>'))
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
})
|
|
319
|
-
|
|
320
|
-
$('img').each((index, elem) => {
|
|
321
|
-
let url = $(elem).attr('src') || ''
|
|
322
|
-
let image = epubConfigs.images.find((el) => el.url === url)
|
|
323
|
-
let id: string
|
|
324
|
-
let extension: string
|
|
325
|
-
|
|
326
|
-
if (image) {
|
|
327
|
-
id = image.id
|
|
328
|
-
extension = image.extension
|
|
329
|
-
} else {
|
|
330
|
-
id = uuidv4()
|
|
331
|
-
let mediaType: string = mime.getType(url.replace(/\?.*/, '')) || ''
|
|
332
|
-
extension = mime.getExtension(mediaType) || ''
|
|
333
|
-
let dir = chapter.dir || ''
|
|
334
|
-
|
|
335
|
-
let img: IEpubImage = { id, url, dir, mediaType, extension }
|
|
336
|
-
epubConfigs.images.push(img)
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
$(elem).attr('src', `images/${id}.${extension}`)
|
|
340
|
-
})
|
|
341
|
-
|
|
342
|
-
chapter.data = $.xml()
|
|
343
|
-
|
|
344
|
-
if (Array.isArray(chapter.children)) {
|
|
345
|
-
chapter.children = chapter.children.map((content, idx) =>
|
|
346
|
-
parseContent(content, `${index}_${idx}`, epubConfigs),
|
|
347
|
-
)
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
return chapter
|
|
351
|
-
}
|
package/src/render.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* render
|
|
3
|
-
* @author: oldj
|
|
4
|
-
* @homepage: https://oldj.net
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import * as archiver from 'archiver'
|
|
8
|
-
import * as fs from 'fs-extra'
|
|
9
|
-
import * as path from 'path'
|
|
10
|
-
import { downloadAllImages } from './downloadImage'
|
|
11
|
-
import { generateTempFile } from './generateTempFile'
|
|
12
|
-
import makeCover from './makeCover'
|
|
13
|
-
import { IEpubData } from './types'
|
|
14
|
-
import { fileIsStable } from './utils'
|
|
15
|
-
|
|
16
|
-
export async function render(data: IEpubData): Promise<void> {
|
|
17
|
-
let { log } = data
|
|
18
|
-
|
|
19
|
-
log('Generating Template Files...')
|
|
20
|
-
await generateTempFile(data)
|
|
21
|
-
log('Downloading Images...')
|
|
22
|
-
await downloadAllImages(data)
|
|
23
|
-
log('Making Cover...')
|
|
24
|
-
await makeCover(data)
|
|
25
|
-
log('Generating Epub Files...')
|
|
26
|
-
await genEpub(data)
|
|
27
|
-
if (fs.existsSync(data.output)) {
|
|
28
|
-
log('Output: ' + data.output)
|
|
29
|
-
log('Done.')
|
|
30
|
-
} else {
|
|
31
|
-
log('Output fail!')
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async function genEpub(epubData: IEpubData): Promise<void> {
|
|
36
|
-
let { log, dir, output } = epubData
|
|
37
|
-
|
|
38
|
-
let archive = archiver('zip', { zlib: { level: 9 } })
|
|
39
|
-
let outputStream = fs.createWriteStream(epubData.output)
|
|
40
|
-
log('Zipping temp dir to ' + output)
|
|
41
|
-
|
|
42
|
-
return new Promise((resolve, reject) => {
|
|
43
|
-
archive.on('end', async () => {
|
|
44
|
-
log('Done zipping, clearing temp dir...')
|
|
45
|
-
|
|
46
|
-
// log(fs.statSync(epubData.output).size)
|
|
47
|
-
// setTimeout(() => log(fs.statSync(epubData.output).size), 1)
|
|
48
|
-
// setTimeout(() => log(fs.statSync(epubData.output).size), 100)
|
|
49
|
-
// setTimeout(() => log(fs.statSync(epubData.output).size), 1000)
|
|
50
|
-
let stable = await fileIsStable(epubData.output)
|
|
51
|
-
if (!stable) {
|
|
52
|
-
log('Output epub file is not stable!')
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
fs.removeSync(dir)
|
|
57
|
-
resolve()
|
|
58
|
-
} catch (e) {
|
|
59
|
-
log('[Error] ' + e.message)
|
|
60
|
-
reject(e)
|
|
61
|
-
}
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
archive.on('close', () => {
|
|
65
|
-
log('Zip close..')
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
archive.on('finish', () => {
|
|
69
|
-
log('Zip finish..')
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
archive.on('error', (err) => {
|
|
73
|
-
log('[Archive Error] ' + err.message)
|
|
74
|
-
reject(err)
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
archive.pipe(outputStream)
|
|
78
|
-
archive.append('application/epub+zip', { store: true, name: 'mimetype' })
|
|
79
|
-
archive.directory(path.join(dir, 'META-INF'), 'META-INF')
|
|
80
|
-
archive.directory(path.join(dir, 'OEBPS'), 'OEBPS')
|
|
81
|
-
|
|
82
|
-
archive.finalize()
|
|
83
|
-
})
|
|
84
|
-
}
|
package/src/types.d.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* types.d.ts
|
|
3
|
-
* @author: oldj
|
|
4
|
-
* @homepage: https://oldj.net
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export interface IEpubImage {
|
|
8
|
-
id: string
|
|
9
|
-
url: string
|
|
10
|
-
dir: string
|
|
11
|
-
mediaType: string
|
|
12
|
-
extension: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface IEpubGenOptions {
|
|
16
|
-
title: string
|
|
17
|
-
author?: string | string[]
|
|
18
|
-
publisher?: string
|
|
19
|
-
cover: string
|
|
20
|
-
output: string
|
|
21
|
-
version?: 2 | 3
|
|
22
|
-
css?: string
|
|
23
|
-
fonts?: string[]
|
|
24
|
-
lang?: 'en'
|
|
25
|
-
tocTitle?: string
|
|
26
|
-
appendChapterTitles?: boolean // For advanced customizations: absolute path to an OPF template.
|
|
27
|
-
customOpfTemplatePath?: string // For advanced customizations: absolute path to a NCX toc template.
|
|
28
|
-
customHtmlTocTemplatePath?: string // For advanced customizations: absolute path to a HTML toc template.
|
|
29
|
-
customNcxTocTemplatePath?: string
|
|
30
|
-
content: IChapter[] // Book Chapters content. It's should be an array of objects. eg. [{title: "Chapter 1",data: "<div>..."}, {data: ""},...]
|
|
31
|
-
verbose?: boolean // specify whether or not to console.log progress messages, default: false
|
|
32
|
-
description?: string
|
|
33
|
-
date?: string
|
|
34
|
-
tmpDir?: string
|
|
35
|
-
timeoutSeconds?: number
|
|
36
|
-
tocAutoNumber?: boolean
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export interface IEpubData extends IEpubGenOptions {
|
|
40
|
-
id: string
|
|
41
|
-
docHeader: string
|
|
42
|
-
dir: string
|
|
43
|
-
images: IEpubImage[]
|
|
44
|
-
tmpDir: string
|
|
45
|
-
baseDir: string
|
|
46
|
-
_coverMediaType?: string
|
|
47
|
-
_coverExtension?: string
|
|
48
|
-
log: (msg) => void
|
|
49
|
-
content: IChapterData[]
|
|
50
|
-
timeoutSeconds: number
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export interface IChapter {
|
|
54
|
-
id?: string
|
|
55
|
-
title?: string
|
|
56
|
-
author?: string | string[]
|
|
57
|
-
data: string // HTML String of the chapter content. image paths should be absolute path (should start with "http" or "https"), so that they could be downloaded. With the upgrade is possible to use local images (for this the path must start with file: //)
|
|
58
|
-
excludeFromToc?: boolean // default: false
|
|
59
|
-
beforeToc?: boolean // if is shown before Table of content, such like copyright pages. default: false
|
|
60
|
-
filename?: string // specify filename for each chapter
|
|
61
|
-
url?: string
|
|
62
|
-
children?: IChapter[]
|
|
63
|
-
appendChapterTitle?: boolean
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface IChapterData extends IChapter {
|
|
67
|
-
id: string
|
|
68
|
-
href?: string
|
|
69
|
-
dir?: string
|
|
70
|
-
children: IChapterData[]
|
|
71
|
-
filePath: string
|
|
72
|
-
author: string[]
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export interface IOut {
|
|
76
|
-
success?: boolean
|
|
77
|
-
message?: string
|
|
78
|
-
options?: IEpubGenOptions
|
|
79
|
-
}
|