wp-epub-gen 0.1.0
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/.eslintrc.js +24 -0
- package/.mocharc.json +3 -0
- package/.prettierrc.json +19 -0
- package/README.md +87 -0
- package/dist/downloadImage.d.ts +7 -0
- package/dist/downloadImage.js +82 -0
- package/dist/errors.d.ts +10 -0
- package/dist/errors.js +14 -0
- package/dist/generateTempFile.d.ts +7 -0
- package/dist/generateTempFile.js +121 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +128 -0
- package/dist/makeCover.d.ts +7 -0
- package/dist/makeCover.js +63 -0
- package/dist/parseContent.d.ts +7 -0
- package/dist/parseContent.js +330 -0
- package/dist/render.d.ts +7 -0
- package/dist/render.js +90 -0
- package/dist/utils.d.ts +13 -0
- package/dist/utils.js +48 -0
- package/package.json +66 -0
- package/src/downloadImage.ts +75 -0
- package/src/errors.ts +11 -0
- package/src/generateTempFile.ts +144 -0
- package/src/index.ts +152 -0
- package/src/makeCover.ts +52 -0
- package/src/parseContent.ts +350 -0
- package/src/render.ts +84 -0
- package/src/types.d.ts +79 -0
- package/src/utils.ts +39 -0
- package/templates/epub2/content.opf.ejs +57 -0
- package/templates/epub2/toc.xhtml.ejs +26 -0
- package/templates/epub3/content.opf.ejs +86 -0
- package/templates/epub3/toc.xhtml.ejs +38 -0
- package/templates/template.css +46 -0
- package/templates/toc.ncx.ejs +45 -0
- package/test/basic.test.js +28 -0
- package/test/child-page-image.test.js +21 -0
- package/test/data/1.json +21 -0
- package/test/tt.js +16 -0
- package/tsconfig.json +31 -0
- package/webpack.config.js +75 -0
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
parser: '@typescript-eslint/parser',
|
|
3
|
+
parserOptions: {
|
|
4
|
+
project: 'tsconfig.json',
|
|
5
|
+
sourceType: 'module'
|
|
6
|
+
},
|
|
7
|
+
plugins: ['@typescript-eslint/eslint-plugin'],
|
|
8
|
+
extends: [
|
|
9
|
+
'plugin:@typescript-eslint/eslint-recommended',
|
|
10
|
+
'plugin:@typescript-eslint/recommended',
|
|
11
|
+
'prettier',
|
|
12
|
+
'prettier/@typescript-eslint'
|
|
13
|
+
],
|
|
14
|
+
root: true,
|
|
15
|
+
env: {
|
|
16
|
+
node: true,
|
|
17
|
+
jest: true
|
|
18
|
+
},
|
|
19
|
+
rules: {
|
|
20
|
+
'@typescript-eslint/interface-name-prefix': 'off',
|
|
21
|
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
22
|
+
'@typescript-eslint/no-explicit-any': 'off'
|
|
23
|
+
}
|
|
24
|
+
}
|
package/.mocharc.json
ADDED
package/.prettierrc.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"arrowParens": "always",
|
|
3
|
+
"bracketSpacing": true,
|
|
4
|
+
"embeddedLanguageFormatting": "auto",
|
|
5
|
+
"endOfLine": "lf",
|
|
6
|
+
"htmlWhitespaceSensitivity": "css",
|
|
7
|
+
"insertPragma": false,
|
|
8
|
+
"jsxBracketSameLine": false,
|
|
9
|
+
"jsxSingleQuote": false,
|
|
10
|
+
"printWidth": 100,
|
|
11
|
+
"proseWrap": "preserve",
|
|
12
|
+
"quoteProps": "as-needed",
|
|
13
|
+
"requirePragma": false,
|
|
14
|
+
"semi": false,
|
|
15
|
+
"singleQuote": true,
|
|
16
|
+
"tabWidth": 2,
|
|
17
|
+
"trailingComma": "all",
|
|
18
|
+
"useTabs": false
|
|
19
|
+
}
|
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# epub-gen
|
|
2
|
+
|
|
3
|
+
Forked from https://github.com/cyrilis/epub-gen/ .
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
Install the lib and add it as a dependency (recommended), run on your project dir:
|
|
8
|
+
|
|
9
|
+
```shell script
|
|
10
|
+
npm install wp-epub-gen --save
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Then put this in your code:
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
const {epubGen} = require("wp-epub-gen");
|
|
17
|
+
epubGen(option).then(
|
|
18
|
+
() => console.log("Ebook Generated Successfully!"),
|
|
19
|
+
err => console.error("Failed to generate Ebook because of ", err)
|
|
20
|
+
);
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
#### Options
|
|
24
|
+
|
|
25
|
+
- `title`:
|
|
26
|
+
Title of the book
|
|
27
|
+
- `author`:
|
|
28
|
+
Name of the author for the book, string or array, eg. `"Alice"` or `["Alice", "Bob"]`
|
|
29
|
+
- `publisher`:
|
|
30
|
+
Publisher name (optional)
|
|
31
|
+
- `cover`:
|
|
32
|
+
Book cover image (optional), File path (absolute path) or web url, eg. `"http://abc.com/book-cover.jpg"` or `"/User/Alice/images/book-cover.jpg"`
|
|
33
|
+
- `output`
|
|
34
|
+
Out put path (absolute path), you can also path output as the second argument, eg: `epubGen(options, output)`
|
|
35
|
+
- `version`:
|
|
36
|
+
You can specify the version of the generated EPUB, `3` the latest version (http://idpf.org/epub/30) or `2` the previous version (http://idpf.org/epub/201, for better compatibility with older readers). If not specified, will fallback to `3`.
|
|
37
|
+
- `css`:
|
|
38
|
+
If you really hate our css, you can pass css string to replace our default style. eg: `"body {background: #000}"`
|
|
39
|
+
- `fonts`:
|
|
40
|
+
Array of (absolute) paths to custom fonts to include on the book so they can be used on custom css. Ex: if you configure the array to `fonts: ['/path/to/Merriweather.ttf']` you can use the following on the custom CSS:
|
|
41
|
+
```
|
|
42
|
+
@font-face {
|
|
43
|
+
font-family: "Merriweather";
|
|
44
|
+
font-style: normal;
|
|
45
|
+
font-weight: normal;
|
|
46
|
+
src : url("./fonts/Merriweather.ttf");
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
- `lang`:
|
|
50
|
+
Language of the book in 2 letters code (optional). If not specified, will fallback to `en`.
|
|
51
|
+
- `tocTitle`:
|
|
52
|
+
Title of the table of contents. If not specified, will fallback to `Table Of Contents`.
|
|
53
|
+
- `appendChapterTitles`:
|
|
54
|
+
Automatically append the chapter title at the beginning of each contents. You can disable that by specifying `false`.
|
|
55
|
+
- `customOpfTemplatePath`:
|
|
56
|
+
Optional. For advanced customizations: absolute path to an OPF template.
|
|
57
|
+
- `customNcxTocTemplatePath`:
|
|
58
|
+
Optional. For advanced customizations: absolute path to a NCX toc template.
|
|
59
|
+
- `customHtmlTocTemplatePath`:
|
|
60
|
+
Optional. For advanced customizations: absolute path to a HTML toc template.
|
|
61
|
+
- `content`:
|
|
62
|
+
Book Chapters content. It's should be an array of objects. eg. `[{title: "Chapter 1",data: "<div>..."}, {data: ""},...]`
|
|
63
|
+
**Within each chapter object:**
|
|
64
|
+
- `id`:
|
|
65
|
+
optional, a unique ID.
|
|
66
|
+
- `title`:
|
|
67
|
+
optional, Chapter title.
|
|
68
|
+
- `author`:
|
|
69
|
+
optional, if each book author is different, you can fill it.
|
|
70
|
+
- `data`:
|
|
71
|
+
required, 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: //)
|
|
72
|
+
- `excludeFromToc`:
|
|
73
|
+
optional, if is not shown on Table of content, default: false.
|
|
74
|
+
- `beforeToc`:
|
|
75
|
+
optional, if is shown before Table of content, such like copyright pages. default: false.
|
|
76
|
+
- `filename`:
|
|
77
|
+
optional, specify filename for each chapter, default: undefined.
|
|
78
|
+
- `children`:
|
|
79
|
+
optional, an Array contains children contents.
|
|
80
|
+
- `appendChapterTitle`:
|
|
81
|
+
optional, Automatically append the chapter title at the beginning of current chapter, this value will overwrite the global `appendChapterTitles`.
|
|
82
|
+
- `verbose`:
|
|
83
|
+
specify whether or not to console.log progress messages, default: false.
|
|
84
|
+
- `timeoutSeconds`:
|
|
85
|
+
specify timeout in seconds, `0` means no timeout, default: 0.
|
|
86
|
+
- `tocAutoNumber`:
|
|
87
|
+
auto number for TOC, default: false.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* downloadImage
|
|
4
|
+
* @author: oldj
|
|
5
|
+
* @homepage: https://oldj.net
|
|
6
|
+
*/
|
|
7
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
8
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
9
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
10
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
11
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
12
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
13
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.downloadAllImages = void 0;
|
|
18
|
+
const fs = require("fs-extra");
|
|
19
|
+
const path = require("path");
|
|
20
|
+
const request = require("superagent");
|
|
21
|
+
const utils_1 = require("./utils");
|
|
22
|
+
const downloadImage = (epubData, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
23
|
+
let { url } = options;
|
|
24
|
+
let { log } = epubData;
|
|
25
|
+
let epub_dir = epubData.dir;
|
|
26
|
+
if (!url) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
let image_dir = path.join(epub_dir, 'OEBPS', 'images');
|
|
30
|
+
fs.ensureDirSync(image_dir);
|
|
31
|
+
let filename = path.join(image_dir, options.id + '.' + options.extension);
|
|
32
|
+
if (url.startsWith('file://') || url.startsWith('/')) {
|
|
33
|
+
let auxPath = url.replace(/^file:\/\//i, '');
|
|
34
|
+
log(`[Copy 1] '${auxPath}' to '${filename}'`);
|
|
35
|
+
if (fs.existsSync(auxPath)) {
|
|
36
|
+
try {
|
|
37
|
+
fs.copySync(auxPath, filename);
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
log('[Copy 1 Error] ' + e.message);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
log(`[Copy 1 Fail] '${url}' not exists!`);
|
|
45
|
+
}
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
let requestAction;
|
|
49
|
+
if (url.startsWith('http')) {
|
|
50
|
+
requestAction = request.get(url).set({ 'User-Agent': utils_1.USER_AGENT });
|
|
51
|
+
requestAction.pipe(fs.createWriteStream(filename));
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
log(`[Copy 2] '${url}' to '${filename}'`);
|
|
55
|
+
requestAction = fs.createReadStream(path.join(options.dir || '', url));
|
|
56
|
+
requestAction.pipe(fs.createWriteStream(filename));
|
|
57
|
+
}
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
requestAction.on('error', (err) => {
|
|
60
|
+
log('[Download Error] Error while downloading: ' + url);
|
|
61
|
+
log(err);
|
|
62
|
+
fs.unlinkSync(filename);
|
|
63
|
+
// reject(err)
|
|
64
|
+
resolve();
|
|
65
|
+
});
|
|
66
|
+
requestAction.on('end', () => {
|
|
67
|
+
log('[Download Success] ' + url);
|
|
68
|
+
resolve();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
const downloadAllImages = (epubData) => __awaiter(void 0, void 0, void 0, function* () {
|
|
73
|
+
let { images } = epubData;
|
|
74
|
+
if (images.length === 0)
|
|
75
|
+
return;
|
|
76
|
+
fs.ensureDirSync(path.join(epubData.dir, 'OEBPS', 'images'));
|
|
77
|
+
for (let image of images) {
|
|
78
|
+
yield downloadImage(epubData, image);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
exports.downloadAllImages = downloadAllImages;
|
|
82
|
+
//# sourceMappingURL=downloadImage.js.map
|
package/dist/errors.d.ts
ADDED
package/dist/errors.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* errors
|
|
4
|
+
* @author: oldj
|
|
5
|
+
* @homepage: https://oldj.net
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.errors = void 0;
|
|
9
|
+
exports.errors = {
|
|
10
|
+
no_output_path: 'No output path!',
|
|
11
|
+
no_title: 'Title is required.',
|
|
12
|
+
no_content: 'Content is required.',
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* generateTempFile
|
|
4
|
+
* @author: oldj
|
|
5
|
+
* @homepage: https://oldj.net
|
|
6
|
+
*/
|
|
7
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
8
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
9
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
10
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
11
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
12
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
13
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.generateTempFile = void 0;
|
|
18
|
+
const ejs = require("ejs");
|
|
19
|
+
const entities = require("entities");
|
|
20
|
+
const fs = require("fs-extra");
|
|
21
|
+
const path = require("path");
|
|
22
|
+
const utils_1 = require("./utils");
|
|
23
|
+
const generateTempFile = (epubData) => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
|
+
var _a;
|
|
25
|
+
let { log } = epubData;
|
|
26
|
+
let oebps_dir = path.join(epubData.dir, 'OEBPS');
|
|
27
|
+
yield fs.ensureDir(oebps_dir);
|
|
28
|
+
const templates_dir = path.join(epubData.baseDir, 'templates');
|
|
29
|
+
epubData.css =
|
|
30
|
+
epubData.css ||
|
|
31
|
+
(yield (0, utils_1.readFile)(path.join(epubData.baseDir, 'templates', 'template.css'), 'utf-8'));
|
|
32
|
+
yield (0, utils_1.writeFile)(path.join(oebps_dir, 'style.css'), epubData.css, 'utf-8');
|
|
33
|
+
if ((_a = epubData.fonts) === null || _a === void 0 ? void 0 : _a.length) {
|
|
34
|
+
let fonts_dir = path.join(oebps_dir, 'fonts');
|
|
35
|
+
yield fs.ensureDir(fonts_dir);
|
|
36
|
+
epubData.fonts = epubData.fonts.map((font) => {
|
|
37
|
+
let filename = path.basename(font);
|
|
38
|
+
if (!fs.existsSync(font)) {
|
|
39
|
+
log(`Custom font not found at '${font}'.`);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
fs.copySync(font, path.join(fonts_dir, filename));
|
|
43
|
+
}
|
|
44
|
+
return filename;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
const isAppendTitle = (global_append, local_append) => {
|
|
48
|
+
if (typeof local_append === 'boolean')
|
|
49
|
+
return local_append;
|
|
50
|
+
return !!global_append;
|
|
51
|
+
};
|
|
52
|
+
const saveContentToFile = (content) => {
|
|
53
|
+
var _a;
|
|
54
|
+
let title = entities.encodeXML(content.title || '');
|
|
55
|
+
let html = `${epubData.docHeader}
|
|
56
|
+
<head>
|
|
57
|
+
<meta charset="UTF-8" />
|
|
58
|
+
<title>${title}</title>
|
|
59
|
+
<link rel="stylesheet" type="text/css" href="style.css" />
|
|
60
|
+
</head>
|
|
61
|
+
<body>
|
|
62
|
+
`;
|
|
63
|
+
if (content.title && isAppendTitle(epubData.appendChapterTitles, content.appendChapterTitle)) {
|
|
64
|
+
html += `<h1>${title}</h1>`;
|
|
65
|
+
}
|
|
66
|
+
html +=
|
|
67
|
+
content.title && content.author && ((_a = content.author) === null || _a === void 0 ? void 0 : _a.length)
|
|
68
|
+
? `<p class='epub-author'>${entities.encodeXML(content.author.join(', '))}</p>`
|
|
69
|
+
: '';
|
|
70
|
+
html +=
|
|
71
|
+
content.title && content.url
|
|
72
|
+
? `<p class="epub-link"><a href="${content.url}">${content.url}</a></p>`
|
|
73
|
+
: '';
|
|
74
|
+
html += `${content.data}`;
|
|
75
|
+
html += '\n</body>\n</html>';
|
|
76
|
+
fs.ensureDirSync(path.dirname(content.filePath));
|
|
77
|
+
fs.writeFileSync(content.filePath, html, 'utf-8');
|
|
78
|
+
if (Array.isArray(content.children)) {
|
|
79
|
+
content.children.map(saveContentToFile);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
epubData.content.map(saveContentToFile);
|
|
83
|
+
// write meta-inf/container.xml
|
|
84
|
+
let metainf_dir = path.join(epubData.dir, 'META-INF');
|
|
85
|
+
fs.ensureDirSync(metainf_dir);
|
|
86
|
+
fs.writeFileSync(path.join(metainf_dir, 'container.xml'), `<?xml version="1.0" encoding="UTF-8" ?>
|
|
87
|
+
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
|
|
88
|
+
<rootfiles><rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml"/></rootfiles>
|
|
89
|
+
</container>`, 'utf-8');
|
|
90
|
+
if (epubData.version === 2) {
|
|
91
|
+
let fn = path.join(metainf_dir, 'com.apple.ibooks.display-options.xml');
|
|
92
|
+
fs.writeFileSync(fn, `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
93
|
+
<display_options>
|
|
94
|
+
<platform name="*">
|
|
95
|
+
<option name="specified-fonts">true</option>
|
|
96
|
+
</platform>
|
|
97
|
+
</display_options>
|
|
98
|
+
`, 'utf-8');
|
|
99
|
+
}
|
|
100
|
+
let opfPath = epubData.customOpfTemplatePath ||
|
|
101
|
+
path.join(templates_dir, `epub${epubData.version}`, 'content.opf.ejs');
|
|
102
|
+
if (!fs.existsSync(opfPath)) {
|
|
103
|
+
throw new Error('Custom file to OPF template not found.');
|
|
104
|
+
}
|
|
105
|
+
let ncxTocPath = epubData.customNcxTocTemplatePath || path.join(templates_dir, `toc.ncx.ejs`);
|
|
106
|
+
if (!fs.existsSync(ncxTocPath)) {
|
|
107
|
+
throw new Error('Custom file the NCX toc template not found.');
|
|
108
|
+
}
|
|
109
|
+
let htmlTocPath = epubData.customHtmlTocTemplatePath ||
|
|
110
|
+
path.join(templates_dir, `epub${epubData.version}`, 'toc.xhtml.ejs');
|
|
111
|
+
if (!fs.existsSync(htmlTocPath)) {
|
|
112
|
+
throw new Error('Custom file to HTML toc template not found.');
|
|
113
|
+
}
|
|
114
|
+
let toc_depth = 1;
|
|
115
|
+
fs.writeFileSync(path.join(oebps_dir, 'content.opf'), yield ejs.renderFile(opfPath, epubData), 'utf-8');
|
|
116
|
+
fs.writeFileSync(path.join(oebps_dir, 'toc.ncx'), yield ejs.renderFile(ncxTocPath, Object.assign(Object.assign({}, epubData), { toc_depth })), 'utf-8');
|
|
117
|
+
// 说明:toc.xhtml 的内容在 macOS 自带的 Books 会被当作目录显示,如果空格太多,目录显示可能会不正常,因此这儿简单去掉了不必要的空格
|
|
118
|
+
fs.writeFileSync(path.join(oebps_dir, 'toc.xhtml'), (0, utils_1.simpleMinifier)(yield ejs.renderFile(htmlTocPath, epubData)), 'utf-8');
|
|
119
|
+
});
|
|
120
|
+
exports.generateTempFile = generateTempFile;
|
|
121
|
+
//# sourceMappingURL=generateTempFile.js.map
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* index.ts
|
|
4
|
+
* @author: oldj
|
|
5
|
+
* @homepage: https://oldj.net
|
|
6
|
+
*/
|
|
7
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
8
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
9
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
10
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
11
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
12
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
13
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.gen = exports.epubGen = void 0;
|
|
18
|
+
const mime = require("mime");
|
|
19
|
+
const os = require("os");
|
|
20
|
+
const path = require("path");
|
|
21
|
+
const uuid_1 = require("uuid");
|
|
22
|
+
const errors_1 = require("./errors");
|
|
23
|
+
const parseContent_1 = require("./parseContent");
|
|
24
|
+
const render_1 = require("./render");
|
|
25
|
+
const baseDir = path.dirname(__dirname);
|
|
26
|
+
function result(success, message, options) {
|
|
27
|
+
if (options && options.verbose) {
|
|
28
|
+
if (!success) {
|
|
29
|
+
console.error(new Error(message));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
let out = {
|
|
33
|
+
success,
|
|
34
|
+
};
|
|
35
|
+
if (typeof message === 'string') {
|
|
36
|
+
out.message = message;
|
|
37
|
+
}
|
|
38
|
+
if (options) {
|
|
39
|
+
out.options = options;
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
function check(options) {
|
|
44
|
+
if (!options.output) {
|
|
45
|
+
return result(false, errors_1.errors.no_output_path, options);
|
|
46
|
+
}
|
|
47
|
+
if (!options.title) {
|
|
48
|
+
return result(false, errors_1.errors.no_title, options);
|
|
49
|
+
}
|
|
50
|
+
if (!options.content) {
|
|
51
|
+
return result(false, errors_1.errors.no_content, options);
|
|
52
|
+
}
|
|
53
|
+
return result(true, undefined, options);
|
|
54
|
+
}
|
|
55
|
+
function parseOptions(options) {
|
|
56
|
+
let tmpDir = options.tmpDir || os.tmpdir();
|
|
57
|
+
let id = (0, uuid_1.v4)();
|
|
58
|
+
let data = Object.assign(Object.assign({ description: options.title, publisher: 'anonymous', author: ['anonymous'], tocTitle: 'Table Of Contents', appendChapterTitles: true, date: new Date().toISOString(), lang: 'en', fonts: [], version: 3, verbose: true, timeoutSeconds: 15 * 60, tocAutoNumber: false }, options), { id,
|
|
59
|
+
tmpDir, dir: path.resolve(tmpDir, id), baseDir, docHeader: '', images: [], content: [], log: (msg) => options.verbose && console.log(msg) });
|
|
60
|
+
if (data.version === 2) {
|
|
61
|
+
data.docHeader = `<?xml version="1.0" encoding="UTF-8"?>
|
|
62
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
|
63
|
+
<html xmlns="http://www.w3.org/1999/xhtml" lang="#{self.options.lang}">
|
|
64
|
+
`;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
data.docHeader = `<?xml version="1.0" encoding="UTF-8"?>
|
|
68
|
+
<!DOCTYPE html>
|
|
69
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" lang="#{self.options.lang}">
|
|
70
|
+
`;
|
|
71
|
+
}
|
|
72
|
+
if (Array.isArray(data.author) && data.author.length === 0) {
|
|
73
|
+
data.author = ['anonymous'];
|
|
74
|
+
}
|
|
75
|
+
if (typeof data.author === 'string') {
|
|
76
|
+
data.author = [data.author];
|
|
77
|
+
}
|
|
78
|
+
data.content = options.content.map((content, index) => (0, parseContent_1.default)(content, index, data));
|
|
79
|
+
if (data.cover) {
|
|
80
|
+
data._coverMediaType = mime.getType(data.cover) || '';
|
|
81
|
+
data._coverExtension = mime.getExtension(data._coverMediaType) || '';
|
|
82
|
+
}
|
|
83
|
+
return data;
|
|
84
|
+
}
|
|
85
|
+
function epubGen(options, output) {
|
|
86
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
87
|
+
options = Object.assign({}, options);
|
|
88
|
+
if (output) {
|
|
89
|
+
options.output = output;
|
|
90
|
+
}
|
|
91
|
+
let o = check(options);
|
|
92
|
+
let verbose = options.verbose !== false;
|
|
93
|
+
if (!o.success) {
|
|
94
|
+
if (verbose)
|
|
95
|
+
console.error(o.message);
|
|
96
|
+
return o;
|
|
97
|
+
}
|
|
98
|
+
let t;
|
|
99
|
+
try {
|
|
100
|
+
let data = parseOptions(options);
|
|
101
|
+
let timeoutSeconds = data.timeoutSeconds || 0;
|
|
102
|
+
if (timeoutSeconds > 0) {
|
|
103
|
+
if (verbose)
|
|
104
|
+
console.log(`TIMEOUT: ${timeoutSeconds}s`);
|
|
105
|
+
t = setTimeout(() => {
|
|
106
|
+
throw new Error('timeout!');
|
|
107
|
+
}, timeoutSeconds * 1000);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
if (verbose)
|
|
111
|
+
console.log(`TIMEOUT: N/A`);
|
|
112
|
+
}
|
|
113
|
+
yield (0, render_1.render)(data);
|
|
114
|
+
return result(true, undefined, data);
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
if (verbose)
|
|
118
|
+
console.error(e);
|
|
119
|
+
return result(false, e.message, options);
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
clearTimeout(t);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
exports.epubGen = epubGen;
|
|
127
|
+
exports.gen = epubGen;
|
|
128
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* makeCover
|
|
4
|
+
* @author: oldj
|
|
5
|
+
* @homepage: https://oldj.net
|
|
6
|
+
*/
|
|
7
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
8
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
9
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
10
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
11
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
12
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
13
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
const fs = require("fs-extra");
|
|
18
|
+
const path = require("path");
|
|
19
|
+
const request = require("superagent");
|
|
20
|
+
const utils_1 = require("./utils");
|
|
21
|
+
function makeCover(data) {
|
|
22
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
23
|
+
let { cover, _coverExtension, log } = data;
|
|
24
|
+
if (!cover)
|
|
25
|
+
return;
|
|
26
|
+
let destPath = path.join(data.dir, 'OEBPS', `cover.${_coverExtension}`);
|
|
27
|
+
let writeStream = null;
|
|
28
|
+
if (cover.startsWith('http')) {
|
|
29
|
+
writeStream = request.get(cover).set({ 'User-Agent': utils_1.USER_AGENT });
|
|
30
|
+
writeStream.pipe(fs.createWriteStream(destPath));
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
if (!fs.existsSync(cover))
|
|
34
|
+
return;
|
|
35
|
+
log('local cover image: ' + cover);
|
|
36
|
+
writeStream = fs.createReadStream(cover);
|
|
37
|
+
writeStream.pipe(fs.createWriteStream(destPath));
|
|
38
|
+
}
|
|
39
|
+
return new Promise((resolve) => {
|
|
40
|
+
writeStream.on('end', () => {
|
|
41
|
+
log('[Success] cover image saved.');
|
|
42
|
+
resolve();
|
|
43
|
+
});
|
|
44
|
+
writeStream.on('error', (e) => {
|
|
45
|
+
log('[Error] cover image error: ' + e.message);
|
|
46
|
+
log('destPath: ' + destPath);
|
|
47
|
+
if (fs.existsSync(destPath)) {
|
|
48
|
+
try {
|
|
49
|
+
fs.unlinkSync(destPath);
|
|
50
|
+
log('destPath removed.');
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
log('[Error] remove cover image error: ' + e.message);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
resolve(e);
|
|
57
|
+
// throw new Error('[Fail] cover image save fail!')
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
exports.default = makeCover;
|
|
63
|
+
//# sourceMappingURL=makeCover.js.map
|