mirror of
https://github.com/Mintplex-Labs/epub2-static.git
synced 2026-07-01 16:04:13 -04:00
3.0.2 pin+patch
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
Copyright (c) 2011 Andris Reinman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,158 @@
|
||||
# epub2
|
||||
|
||||
**epub2** is a node.js module to parse EPUB electronic book files.
|
||||
|
||||
**NB!** Only ebooks in UTF-8 are currently supported!.
|
||||
|
||||
***this module fork from*** `epub`
|
||||
|
||||
## Installation
|
||||
|
||||
npm install epub2 zipfile
|
||||
|
||||
Or, if you want a pure-JS version (useful if used in a Node-Webkit app for example):
|
||||
|
||||
npm install epub2
|
||||
|
||||
## Usage
|
||||
|
||||
* [example](test/example/example.ts)
|
||||
* [example Promise](test/example/example2.ts)
|
||||
|
||||
```ts
|
||||
const EPub = require("epub2/node");
|
||||
import * as EPub from 'epub2/node';
|
||||
|
||||
const EPub = require("epub2").EPub;
|
||||
import EPub from 'epub2';
|
||||
import { EPub } from 'epub2';
|
||||
```
|
||||
|
||||
```ts
|
||||
var epub = new EPub(epubfile, imagewebroot, chapterwebroot);
|
||||
```
|
||||
|
||||
Where
|
||||
|
||||
* **epubfile** is the file path to an EPUB file
|
||||
* **imagewebroot** is the prefix for image URL's. If it's */images/* then the actual URL (inside chapter HTML `<img>` blocks) is going to be */images/IMG_ID/IMG_FILENAME*, `IMG_ID` can be used to fetch the image form the ebook with `getImage`. Default: `/images/`
|
||||
* **chapterwebroot** is the prefix for chapter URL's. If it's */chapter/* then the actual URL (inside chapter HTML `<a>` links) is going to be */chapters/CHAPTER_ID/CHAPTER_FILENAME*, `CHAPTER_ID` can be used to fetch the image form the ebook with `getChapter`. Default: `/links/`
|
||||
|
||||
Before the contents of the ebook can be read, it must be opened (`EPub` is an `EventEmitter`).
|
||||
|
||||
### async
|
||||
|
||||
```ts
|
||||
let epub = await EPub.createAsync(epubfile, imagewebroot, chapterwebroot);
|
||||
```
|
||||
|
||||
```ts
|
||||
EPub.createAsync(epubfile, imagewebroot, chapterwebroot)
|
||||
.then(function (epub)
|
||||
{
|
||||
...
|
||||
})
|
||||
.catch(function (err)
|
||||
{
|
||||
console.log("ERROR\n-----");
|
||||
throw err;
|
||||
})
|
||||
;
|
||||
```
|
||||
|
||||
### old way
|
||||
|
||||
```ts
|
||||
epub.on("end", function(){
|
||||
// epub is now usable
|
||||
console.log(epub.metadata.title);
|
||||
|
||||
epub.getChapter("chapter_id", function(err, text){});
|
||||
});
|
||||
epub.parse();
|
||||
```
|
||||
|
||||
## metadata
|
||||
|
||||
Property of the *epub* object that holds several metadata fields about the book.
|
||||
|
||||
```ts
|
||||
epub = new EPub(...);
|
||||
...
|
||||
epub.metadata;
|
||||
```
|
||||
|
||||
```ts
|
||||
// raw metadata
|
||||
epub.metadata[EPub.SYMBOL_RAW_DATA];
|
||||
```
|
||||
|
||||
Available fields:
|
||||
|
||||
* **creator** Author of the book (if multiple authors, then the first on the list) (*Lewis Carroll*)
|
||||
* **creatorFileAs** Author name on file (*Carroll, Lewis*)
|
||||
* **title** Title of the book (*Alice's Adventures in Wonderland*)
|
||||
* **language** Language code (*en* or *en-us* etc.)
|
||||
* **subject** Topic of the book (*Fantasy*)
|
||||
* **date** creation of the file (*2006-08-12*)
|
||||
* **description**
|
||||
|
||||
## flow
|
||||
|
||||
*flow* is a property of the *epub* object and holds the actual list of chapters (TOC is just an indication and can link to a # url inside a chapter file)
|
||||
|
||||
```ts
|
||||
epub = new EPub(...);
|
||||
...
|
||||
epub.flow.forEach(function(chapter){
|
||||
console.log(chapter.id);
|
||||
});
|
||||
```
|
||||
|
||||
Chapter `id` is needed to load the chapters `getChapter`
|
||||
|
||||
## toc
|
||||
*toc* is a property of the *epub* object and indicates a list of titles/urls for the TOC. Actual chapter and it's ID needs to be detected with the `href` property
|
||||
|
||||
|
||||
## getChapter(chapter_id, callback)
|
||||
|
||||
Load chapter text from the ebook.
|
||||
|
||||
```ts
|
||||
var epub = new EPub(...);
|
||||
...
|
||||
epub.getChapter("chapter1", function(error, text){});
|
||||
```
|
||||
|
||||
## getChapterRaw(chapter_id, callback)
|
||||
|
||||
Load raw chapter text from the ebook.
|
||||
|
||||
## getImage(image_id, callback)
|
||||
|
||||
Load image (as a Buffer value) from the ebook.
|
||||
|
||||
```ts
|
||||
var epub = new EPub(...);
|
||||
...
|
||||
epub.getImage("image1", function(error, img, mimeType){});
|
||||
```
|
||||
|
||||
## getFile(file_id, callback)
|
||||
|
||||
Load any file (as a Buffer value) from the ebook.
|
||||
|
||||
```ts
|
||||
var epub = new EPub(...);
|
||||
...
|
||||
epub.getFile("css1", function(error, data, mimeType){});
|
||||
```
|
||||
|
||||
## EPub.libPromise
|
||||
|
||||
change Promise class
|
||||
|
||||
```ts
|
||||
EPub.libPromise = Promise;
|
||||
```
|
||||
@@ -0,0 +1,44 @@
|
||||
"use strict";
|
||||
const epub_1 = require("./lib/epub");
|
||||
module.exports = epub_1.EPub;
|
||||
/*
|
||||
// @ts-ignore
|
||||
declare module "epub"
|
||||
{
|
||||
|
||||
import { EventEmitter } from "events";
|
||||
|
||||
interface TocElement
|
||||
{
|
||||
level: number;
|
||||
order: number;
|
||||
title: string;
|
||||
id: string;
|
||||
href?: string;
|
||||
}
|
||||
|
||||
class EPub extends EventEmitter
|
||||
{
|
||||
constructor(epubfile: string, imagewebroot?: string, chapterwebroot?: string);
|
||||
|
||||
metadata: Object;
|
||||
manifest: Object;
|
||||
spine: Object;
|
||||
flow: Array<Object>;
|
||||
toc: Array<TocElement>;
|
||||
|
||||
parse(): void;
|
||||
|
||||
getChapter(chapterId: string, callback: (error: Error, text: string) => void): void;
|
||||
|
||||
getChapterRaw(chapterId: string, callback: (error: Error, text: string) => void): void;
|
||||
|
||||
getImage(id: string, callback: (error: Error, data: Buffer, mimeType: string) => void): void;
|
||||
|
||||
getFile(id: string, callback: (error: Error, data: Buffer, mimeType: string) => void): void;
|
||||
}
|
||||
|
||||
export = EPub;
|
||||
}
|
||||
*/
|
||||
//# sourceMappingURL=epub.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"epub.js","sourceRoot":"","sources":["epub.ts"],"names":[],"mappings":";AAAA,qCAAkC;AAIlC,iBAAS,WAAI,CAAC;AAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuCE","sourcesContent":["import { EPub } from './lib/epub';\n\n//TODO: Cache parsed data\n\nexport = EPub;\n\n/*\n// @ts-ignore\ndeclare module \"epub\"\n{\n\n\timport { EventEmitter } from \"events\";\n\n\tinterface TocElement\n\t{\n\t\tlevel: number;\n\t\torder: number;\n\t\ttitle: string;\n\t\tid: string;\n\t\thref?: string;\n\t}\n\n\tclass EPub extends EventEmitter\n\t{\n\t\tconstructor(epubfile: string, imagewebroot?: string, chapterwebroot?: string);\n\n\t\tmetadata: Object;\n\t\tmanifest: Object;\n\t\tspine: Object;\n\t\tflow: Array<Object>;\n\t\ttoc: Array<TocElement>;\n\n\t\tparse(): void;\n\n\t\tgetChapter(chapterId: string, callback: (error: Error, text: string) => void): void;\n\n\t\tgetChapterRaw(chapterId: string, callback: (error: Error, text: string) => void): void;\n\n\t\tgetImage(id: string, callback: (error: Error, data: Buffer, mimeType: string) => void): void;\n\n\t\tgetFile(id: string, callback: (error: Error, data: Buffer, mimeType: string) => void): void;\n\t}\n\n\texport = EPub;\n}\n*/\n"]}
|
||||
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Created by user on 2018/2/1/001.
|
||||
*/
|
||||
/// <reference types="node" />
|
||||
import Promise from 'bluebird';
|
||||
import xml2js from 'xml2js';
|
||||
import { EPub as libEPub } from './lib/epub';
|
||||
import { TocElement } from './lib/epub/const';
|
||||
export { SYMBOL_RAW_DATA } from './lib/types';
|
||||
export declare class EPub extends libEPub {
|
||||
static createAsync(epubfile: string, imagewebroot?: string, chapterwebroot?: string, ...argv: any[]): Promise<EPub>;
|
||||
protected _p_method_cb<T>(method: any, options?: Promise.FromNodeOptions, ...argv: any[]): Promise<T>;
|
||||
getChapterAsync(chapterId: string): Promise<string>;
|
||||
getChapterRawAsync(chapterId: string): Promise<string>;
|
||||
getFileAsync(id: string): Promise<[Buffer, string]>;
|
||||
getImageAsync(id: string): Promise<[Buffer, string]>;
|
||||
listImage(): TocElement[];
|
||||
static xml2jsOptions: xml2js.Options;
|
||||
/**
|
||||
* allow change Promise class
|
||||
* @type {PromiseConstructor}
|
||||
*/
|
||||
static libPromise: typeof Promise;
|
||||
}
|
||||
export default EPub;
|
||||
@@ -0,0 +1,93 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Created by user on 2018/2/1/001.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.EPub = exports.SYMBOL_RAW_DATA = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const bluebird_1 = tslib_1.__importDefault(require("bluebird"));
|
||||
const path_1 = tslib_1.__importDefault(require("path"));
|
||||
const epub_1 = require("./lib/epub");
|
||||
var types_1 = require("./lib/types");
|
||||
Object.defineProperty(exports, "SYMBOL_RAW_DATA", { enumerable: true, get: function () { return types_1.SYMBOL_RAW_DATA; } });
|
||||
class EPub extends epub_1.EPub {
|
||||
static createAsync(epubfile, imagewebroot, chapterwebroot, ...argv) {
|
||||
const self = this;
|
||||
const p = self.libPromise;
|
||||
return new p(function (resolve, reject) {
|
||||
const epub = self.create(epubfile, imagewebroot, chapterwebroot, ...argv);
|
||||
const cb_err = function (err) {
|
||||
err.epub = epub;
|
||||
return reject(err);
|
||||
};
|
||||
epub.on('error', cb_err);
|
||||
epub.on('end', function (err) {
|
||||
if (err) {
|
||||
cb_err(err);
|
||||
}
|
||||
else {
|
||||
// @ts-ignore
|
||||
resolve(this);
|
||||
}
|
||||
});
|
||||
epub.parse();
|
||||
});
|
||||
}
|
||||
_p_method_cb(method, options = {}, ...argv) {
|
||||
const self = this;
|
||||
const p = this._getStatic().libPromise;
|
||||
return bluebird_1.default.fromCallback(method.bind(self, argv), options);
|
||||
}
|
||||
getChapterAsync(chapterId) {
|
||||
return this._p_method_cb(this.getChapter, null, chapterId);
|
||||
}
|
||||
getChapterRawAsync(chapterId) {
|
||||
return this._p_method_cb(this.getChapterRaw, null, chapterId);
|
||||
}
|
||||
getFileAsync(id) {
|
||||
return this._p_method_cb(this.getFile, {
|
||||
multiArgs: true,
|
||||
}, id);
|
||||
}
|
||||
getImageAsync(id) {
|
||||
return this._p_method_cb(this.getImage, {
|
||||
multiArgs: true,
|
||||
}, id);
|
||||
}
|
||||
listImage() {
|
||||
const epub = this;
|
||||
const mimes = [
|
||||
'image/jpeg',
|
||||
];
|
||||
const exts = [
|
||||
'jpg',
|
||||
'png',
|
||||
'gif',
|
||||
'webp',
|
||||
'tif',
|
||||
'bmp',
|
||||
//'jxr',
|
||||
//'psd'
|
||||
];
|
||||
return Object.keys(epub.manifest)
|
||||
.reduce(function (a, id) {
|
||||
let elem = epub.manifest[id];
|
||||
let mime = elem['media-type'] || elem.mediaType;
|
||||
if (mimes.includes(mime) || mime.indexOf('image') == 0 || exts.includes(path_1.default.extname(elem.href))) {
|
||||
a.push(elem);
|
||||
}
|
||||
return a;
|
||||
}, []);
|
||||
}
|
||||
}
|
||||
exports.EPub = EPub;
|
||||
EPub.xml2jsOptions = Object.assign({}, epub_1.EPub.xml2jsOptions, {
|
||||
normalize: null,
|
||||
});
|
||||
/**
|
||||
* allow change Promise class
|
||||
* @type {PromiseConstructor}
|
||||
*/
|
||||
EPub.libPromise = bluebird_1.default;
|
||||
exports.default = EPub;
|
||||
//# sourceMappingURL=index.js.map
|
||||
File diff suppressed because one or more lines are too long
Vendored
+175
@@ -0,0 +1,175 @@
|
||||
/**
|
||||
* Created by user on 2020/6/10.
|
||||
*/
|
||||
/// <reference types="node" />
|
||||
/// <reference types="node" />
|
||||
import { EventEmitter } from "events";
|
||||
import { IZipFile } from '../zipfile';
|
||||
import xml2js from 'xml2js';
|
||||
import { IMetadata, IMetadataList, INcx, INcxTree, ISpine, ISpineContents, TocElement } from "./epub/const";
|
||||
/**
|
||||
* new EPub(fname[, imageroot][, linkroot])
|
||||
* - fname (String): filename for the ebook
|
||||
* - imageroot (String): URL prefix for images
|
||||
* - linkroot (String): URL prefix for links
|
||||
*
|
||||
* Creates an Event Emitter type object for parsing epub files
|
||||
*
|
||||
* var epub = new EPub("book.epub");
|
||||
* epub.on("end", function () {
|
||||
* console.log(epub.spine);
|
||||
* });
|
||||
* epub.on("error", function (error) { ... });
|
||||
* epub.parse();
|
||||
*
|
||||
* Image and link URL format is:
|
||||
*
|
||||
* imageroot + img_id + img_zip_path
|
||||
*
|
||||
* So an image "logo.jpg" which resides in "OPT/" in the zip archive
|
||||
* and is listed in the manifest with id "logo_img" will have the
|
||||
* following url (providing that imageroot is "/images/"):
|
||||
*
|
||||
* /images/logo_img/OPT/logo.jpg
|
||||
**/
|
||||
export declare class EPub extends EventEmitter {
|
||||
metadata: IMetadata;
|
||||
manifest: IMetadataList;
|
||||
spine: ISpine;
|
||||
flow: ISpineContents;
|
||||
toc: ISpineContents;
|
||||
ncx: INcx;
|
||||
ncx_depth: number;
|
||||
filename: string;
|
||||
imageroot: string;
|
||||
linkroot: string;
|
||||
containerFile: string;
|
||||
mimeFile: string;
|
||||
rootFile: string;
|
||||
zip: IZipFile;
|
||||
version: string;
|
||||
protected _getStatic(): any;
|
||||
constructor(epubfile: string, imagewebroot?: string, chapterwebroot?: string, ...argv: any[]);
|
||||
static create(epubfile: string, imagewebroot?: string, chapterwebroot?: string, ...argv: any[]): EPub;
|
||||
/**
|
||||
* EPub#parse() -> undefined
|
||||
*
|
||||
* Starts the parser, needs to be called by the script
|
||||
**/
|
||||
parse(): this;
|
||||
/**
|
||||
* EPub#open() -> undefined
|
||||
*
|
||||
* Opens the epub file with Zip unpacker, retrieves file listing
|
||||
* and runs mime type check
|
||||
**/
|
||||
open(): void;
|
||||
/**
|
||||
* EPub#checkMimeType() -> undefined
|
||||
*
|
||||
* Checks if there's a file called "mimetype" and that it's contents
|
||||
* are "application/epub+zip". On success runs root file check.
|
||||
**/
|
||||
checkMimeType(): void;
|
||||
protected _Elem(element: TocElement): TocElement;
|
||||
/**
|
||||
* EPub#getRootFiles() -> undefined
|
||||
*
|
||||
* Looks for a "meta-inf/container.xml" file and searches for a
|
||||
* rootfile element with mime type "application/oebps-package+xml".
|
||||
* On success calls the rootfile parser
|
||||
**/
|
||||
getRootFiles(): void;
|
||||
/**
|
||||
* EPub#handleRootFile() -> undefined
|
||||
*
|
||||
* Parses the rootfile XML and calls rootfile parser
|
||||
**/
|
||||
handleRootFile(): void;
|
||||
/**
|
||||
* EPub#parseRootFile() -> undefined
|
||||
*
|
||||
* Parses elements "metadata," "manifest," "spine" and TOC.
|
||||
* Emits "end" if no TOC
|
||||
**/
|
||||
parseRootFile(rootfile: any): void;
|
||||
/**
|
||||
* EPub#parseMetadata() -> undefined
|
||||
*
|
||||
* Parses "metadata" block (book metadata, title, author etc.)
|
||||
**/
|
||||
parseMetadata(metadata: IMetadata): void;
|
||||
/**
|
||||
* EPub#parseManifest() -> undefined
|
||||
*
|
||||
* Parses "manifest" block (all items included, html files, images, styles)
|
||||
**/
|
||||
parseManifest(manifest: any): void;
|
||||
/**
|
||||
* EPub#parseSpine() -> undefined
|
||||
*
|
||||
* Parses "spine" block (all html elements that are shown to the reader)
|
||||
**/
|
||||
parseSpine(spine: any): void;
|
||||
/**
|
||||
* EPub#parseTOC() -> undefined
|
||||
*
|
||||
* Parses ncx file for table of contents (title, html file)
|
||||
**/
|
||||
parseTOC(): void;
|
||||
/**
|
||||
* EPub#walkNavMap(branch, path, id_list,[, level]) -> Array
|
||||
* - branch (Array | Object): NCX NavPoint object
|
||||
* - path (Array): Base path
|
||||
* - id_list (Object): map of file paths and id values
|
||||
* - level (Number): deepness
|
||||
*
|
||||
* Walks the NavMap object through all levels and finds elements
|
||||
* for TOC
|
||||
**/
|
||||
walkNavMap(branch: any, path: any, id_list: any, level?: number, pe?: TocElement, parentNcx?: INcxTree, ncx_idx?: any): any[];
|
||||
/**
|
||||
* EPub#getChapter(id, callback) -> undefined
|
||||
* - id (String): Manifest id value for a chapter
|
||||
* - callback (Function): callback function
|
||||
*
|
||||
* Finds a chapter text for an id. Replaces image and link URL's, removes
|
||||
* <head> etc. elements. Return only chapters with mime type application/xhtml+xml
|
||||
**/
|
||||
getChapter(chapterId: string, callback: (error: Error, text?: string) => void): void;
|
||||
/**
|
||||
* EPub#getChapterRaw(id, callback) -> undefined
|
||||
* - id (String): Manifest id value for a chapter
|
||||
* - callback (Function): callback function
|
||||
*
|
||||
* Returns the raw chapter text for an id.
|
||||
**/
|
||||
getChapterRaw(chapterId: string, callback: (error: Error, text?: string) => void): void;
|
||||
/**
|
||||
* EPub#getImage(id, callback) -> undefined
|
||||
* - id (String): Manifest id value for an image
|
||||
* - callback (Function): callback function
|
||||
*
|
||||
* Finds an image for an id. Returns the image as Buffer. Callback gets
|
||||
* an error object, image buffer and image content-type.
|
||||
* Return only images with mime type image
|
||||
**/
|
||||
getImage(id: string, callback: (error: Error, data?: Buffer, mimeType?: string) => void): void;
|
||||
/**
|
||||
* EPub#getFile(id, callback) -> undefined
|
||||
* - id (String): Manifest id value for a file
|
||||
* - callback (Function): callback function
|
||||
*
|
||||
* Finds a file for an id. Returns the file as Buffer. Callback gets
|
||||
* an error object, file contents buffer and file content-type.
|
||||
**/
|
||||
getFile(id: string, callback: (error: Error, data?: Buffer, mimeType?: string) => void): void;
|
||||
readFile(filename: any, options: any, callback_: any): void;
|
||||
static SYMBOL_RAW_DATA: symbol;
|
||||
static readonly IMAGE_ROOT = "/images/";
|
||||
static readonly LINK_ROOT = "/links/";
|
||||
static readonly ELEM_MEDIA_TYPE = "media-type";
|
||||
static readonly ELEM_MEDIA_TYPE2 = "mediaType";
|
||||
static xml2jsOptions: xml2js.Options;
|
||||
}
|
||||
export default EPub;
|
||||
+810
@@ -0,0 +1,810 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Created by user on 2020/6/10.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.EPub = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const events_1 = require("events");
|
||||
const zipfile_1 = require("../zipfile");
|
||||
const xml2js_1 = tslib_1.__importDefault(require("xml2js"));
|
||||
const array_hyper_unique_1 = require("array-hyper-unique");
|
||||
const path_1 = require("path");
|
||||
const url_1 = require("url");
|
||||
const crlf_normalize_1 = require("crlf-normalize");
|
||||
const types_1 = require("./types");
|
||||
const isEpub_1 = require("./epub/isEpub");
|
||||
/**
|
||||
* new EPub(fname[, imageroot][, linkroot])
|
||||
* - fname (String): filename for the ebook
|
||||
* - imageroot (String): URL prefix for images
|
||||
* - linkroot (String): URL prefix for links
|
||||
*
|
||||
* Creates an Event Emitter type object for parsing epub files
|
||||
*
|
||||
* var epub = new EPub("book.epub");
|
||||
* epub.on("end", function () {
|
||||
* console.log(epub.spine);
|
||||
* });
|
||||
* epub.on("error", function (error) { ... });
|
||||
* epub.parse();
|
||||
*
|
||||
* Image and link URL format is:
|
||||
*
|
||||
* imageroot + img_id + img_zip_path
|
||||
*
|
||||
* So an image "logo.jpg" which resides in "OPT/" in the zip archive
|
||||
* and is listed in the manifest with id "logo_img" will have the
|
||||
* following url (providing that imageroot is "/images/"):
|
||||
*
|
||||
* /images/logo_img/OPT/logo.jpg
|
||||
**/
|
||||
class EPub extends events_1.EventEmitter {
|
||||
_getStatic() {
|
||||
// @ts-ignore
|
||||
return this.__proto__.constructor;
|
||||
}
|
||||
constructor(epubfile, imagewebroot, chapterwebroot, ...argv) {
|
||||
super();
|
||||
this.filename = epubfile;
|
||||
this.imageroot = (imagewebroot || this._getStatic().IMAGE_ROOT).trim();
|
||||
this.linkroot = (chapterwebroot || this._getStatic().LINK_ROOT).trim();
|
||||
if (this.imageroot.substr(-1) != "/") {
|
||||
this.imageroot += "/";
|
||||
}
|
||||
if (this.linkroot.substr(-1) != "/") {
|
||||
this.linkroot += "/";
|
||||
}
|
||||
}
|
||||
static create(epubfile, imagewebroot, chapterwebroot, ...argv) {
|
||||
let epub = new this(epubfile, imagewebroot, chapterwebroot, ...argv);
|
||||
return epub;
|
||||
}
|
||||
/**
|
||||
* EPub#parse() -> undefined
|
||||
*
|
||||
* Starts the parser, needs to be called by the script
|
||||
**/
|
||||
parse() {
|
||||
this.containerFile = null;
|
||||
this.mimeFile = null;
|
||||
this.rootFile = null;
|
||||
this.metadata = {};
|
||||
this.manifest = {};
|
||||
this.spine = { toc: null, contents: [] };
|
||||
this.flow = [];
|
||||
this.toc = [];
|
||||
this.open();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* EPub#open() -> undefined
|
||||
*
|
||||
* Opens the epub file with Zip unpacker, retrieves file listing
|
||||
* and runs mime type check
|
||||
**/
|
||||
open() {
|
||||
try {
|
||||
// @ts-ignore
|
||||
this.zip = new zipfile_1.ZipFile(this.filename);
|
||||
}
|
||||
catch (E) {
|
||||
this.emit("error", new Error(`Invalid/missing file ${this.filename}`));
|
||||
return;
|
||||
}
|
||||
if (!this.zip.names || !this.zip.names.length) {
|
||||
this.emit("error", new Error(`No files in archive ${this.filename}`));
|
||||
return;
|
||||
}
|
||||
this.checkMimeType();
|
||||
}
|
||||
/**
|
||||
* EPub#checkMimeType() -> undefined
|
||||
*
|
||||
* Checks if there's a file called "mimetype" and that it's contents
|
||||
* are "application/epub+zip". On success runs root file check.
|
||||
**/
|
||||
checkMimeType() {
|
||||
var i, len;
|
||||
for (i = 0, len = this.zip.names.length; i < len; i++) {
|
||||
if (this.zip.names[i].toLowerCase() == "mimetype") {
|
||||
this.mimeFile = this.zip.names[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!this.mimeFile) {
|
||||
this.emit("error", new Error("No mimetype file in archive"));
|
||||
return;
|
||||
}
|
||||
this.zip.readFile(this.mimeFile, (err, data) => {
|
||||
if (err) {
|
||||
this.emit("error", new Error("Reading archive failed"));
|
||||
return;
|
||||
}
|
||||
if (!(0, isEpub_1.isEpub)(data, true)) {
|
||||
this.emit("error", new Error("Unsupported mime type"));
|
||||
return;
|
||||
}
|
||||
this.getRootFiles();
|
||||
});
|
||||
}
|
||||
_Elem(element) {
|
||||
const SYMBOL_RAW_DATA = this._getStatic().SYMBOL_RAW_DATA;
|
||||
if (!element[SYMBOL_RAW_DATA]) {
|
||||
element[SYMBOL_RAW_DATA] = Object.assign({}, element);
|
||||
}
|
||||
if (element['media-type']) {
|
||||
element['mediaType'] = element['media-type'];
|
||||
}
|
||||
return element;
|
||||
}
|
||||
/**
|
||||
* EPub#getRootFiles() -> undefined
|
||||
*
|
||||
* Looks for a "meta-inf/container.xml" file and searches for a
|
||||
* rootfile element with mime type "application/oebps-package+xml".
|
||||
* On success calls the rootfile parser
|
||||
**/
|
||||
getRootFiles() {
|
||||
var i, len;
|
||||
for (i = 0, len = this.zip.names.length; i < len; i++) {
|
||||
if (this.zip.names[i].toLowerCase() == "meta-inf/container.xml") {
|
||||
this.containerFile = this.zip.names[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!this.containerFile) {
|
||||
this.emit("error", new Error("No container file in archive"));
|
||||
return;
|
||||
}
|
||||
const xml2jsOptions = this._getStatic().xml2jsOptions;
|
||||
this.zip.readFile(this.containerFile, (err, data) => {
|
||||
if (err) {
|
||||
this.emit("error", new Error("Reading archive failed"));
|
||||
return;
|
||||
}
|
||||
let xml = data.toString("utf-8").toLowerCase().trim(), xmlparser = new xml2js_1.default.Parser(xml2jsOptions);
|
||||
let parser = xmlparser.on("end", (result) => {
|
||||
if (!result.rootfiles || !result.rootfiles.rootfile) {
|
||||
this.emit("error", new Error("No rootfiles found"));
|
||||
console.dir(result);
|
||||
return;
|
||||
}
|
||||
var rootfile = result.rootfiles.rootfile, filename = false, i, len;
|
||||
if (Array.isArray(rootfile)) {
|
||||
for (i = 0, len = rootfile.length; i < len; i++) {
|
||||
if (rootfile[i]["@"]["media-type"] &&
|
||||
rootfile[i]["@"]["media-type"] == "application/oebps-package+xml" &&
|
||||
rootfile[i]["@"]["full-path"]) {
|
||||
filename = rootfile[i]["@"]["full-path"].toLowerCase().trim();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rootfile["@"]) {
|
||||
if (rootfile["@"]["media-type"] != "application/oebps-package+xml" || !rootfile["@"]["full-path"]) {
|
||||
this.emit("error", new Error("Rootfile in unknown format"));
|
||||
return;
|
||||
}
|
||||
filename = rootfile["@"]["full-path"].toLowerCase().trim();
|
||||
}
|
||||
if (!filename) {
|
||||
this.emit("error", new Error("Empty rootfile"));
|
||||
return;
|
||||
}
|
||||
for (i = 0, len = this.zip.names.length; i < len; i++) {
|
||||
if (this.zip.names[i].toLowerCase() == filename) {
|
||||
this.rootFile = this.zip.names[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!this.rootFile) {
|
||||
this.emit("error", new Error("Rootfile not found from archive"));
|
||||
return;
|
||||
}
|
||||
this.handleRootFile();
|
||||
});
|
||||
xmlparser.on("error", (err) => {
|
||||
this.emit("error", new Error("Parsing container XML failed"));
|
||||
return;
|
||||
});
|
||||
xmlparser.parseString(xml);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* EPub#handleRootFile() -> undefined
|
||||
*
|
||||
* Parses the rootfile XML and calls rootfile parser
|
||||
**/
|
||||
handleRootFile() {
|
||||
const xml2jsOptions = this._getStatic().xml2jsOptions;
|
||||
this.zip.readFile(this.rootFile, (err, data) => {
|
||||
if (err) {
|
||||
this.emit("error", new Error("Reading archive failed"));
|
||||
return;
|
||||
}
|
||||
var xml = data.toString("utf-8"), xmlparser = new xml2js_1.default.Parser(xml2jsOptions);
|
||||
xmlparser.on("end", this.parseRootFile.bind(this));
|
||||
xmlparser.on("error", (err) => {
|
||||
this.emit("error", new Error("Parsing container XML failed"));
|
||||
return;
|
||||
});
|
||||
xmlparser.parseString(xml);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* EPub#parseRootFile() -> undefined
|
||||
*
|
||||
* Parses elements "metadata," "manifest," "spine" and TOC.
|
||||
* Emits "end" if no TOC
|
||||
**/
|
||||
parseRootFile(rootfile) {
|
||||
this.version = rootfile['@'].version || '2.0';
|
||||
var i, len, keys, keyparts, key;
|
||||
keys = Object.keys(rootfile);
|
||||
for (i = 0, len = keys.length; i < len; i++) {
|
||||
keyparts = keys[i].split(":");
|
||||
key = (keyparts.pop() || "").toLowerCase().trim();
|
||||
switch (key) {
|
||||
case "metadata":
|
||||
this.parseMetadata(rootfile[keys[i]]);
|
||||
break;
|
||||
case "manifest":
|
||||
this.parseManifest(rootfile[keys[i]]);
|
||||
break;
|
||||
case "spine":
|
||||
this.parseSpine(rootfile[keys[i]]);
|
||||
break;
|
||||
case "guide":
|
||||
//this.parseGuide(rootfile[keys[i]]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this.spine.toc) {
|
||||
this.parseTOC();
|
||||
}
|
||||
else {
|
||||
this.emit("end");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* EPub#parseMetadata() -> undefined
|
||||
*
|
||||
* Parses "metadata" block (book metadata, title, author etc.)
|
||||
**/
|
||||
parseMetadata(metadata) {
|
||||
let i, j, len, keys, keyparts, key;
|
||||
const _self = this;
|
||||
this.metadata[types_1.SYMBOL_RAW_DATA] = metadata;
|
||||
keys = Object.keys(metadata);
|
||||
for (i = 0, len = keys.length; i < len; i++) {
|
||||
keyparts = keys[i].split(":");
|
||||
key = (keyparts.pop() || "").toLowerCase().trim();
|
||||
const currentData = metadata[keys[i]];
|
||||
switch (key) {
|
||||
case "publisher":
|
||||
if (Array.isArray(currentData)) {
|
||||
this.metadata.publisher = String(currentData[0] && currentData[0]["#"] || currentData[0] || "")
|
||||
.trim();
|
||||
}
|
||||
else {
|
||||
this.metadata.publisher = String(currentData["#"] || currentData || "").trim();
|
||||
}
|
||||
break;
|
||||
case "language":
|
||||
if (Array.isArray(currentData)) {
|
||||
this.metadata.language = String(currentData[0] && currentData[0]["#"] || currentData[0] || "")
|
||||
.toLowerCase()
|
||||
.trim();
|
||||
}
|
||||
else {
|
||||
this.metadata.language = String(currentData["#"] || currentData || "")
|
||||
.toLowerCase()
|
||||
.trim();
|
||||
}
|
||||
break;
|
||||
case "title":
|
||||
if (Array.isArray(currentData)) {
|
||||
this.metadata.title = String(currentData[0] && currentData[0]["#"] || currentData[0] || "")
|
||||
.trim();
|
||||
}
|
||||
else {
|
||||
this.metadata.title = String(currentData["#"] || currentData || "").trim();
|
||||
}
|
||||
break;
|
||||
case "subject":
|
||||
this.metadata.subject = this.metadata.subject || [];
|
||||
(Array.isArray(currentData) ? currentData : [currentData])
|
||||
.forEach(function (value) {
|
||||
let tag = (_meta_val(value, '#') || '').trim();
|
||||
if (tag !== '') {
|
||||
_self.metadata.subject.push(tag);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "description":
|
||||
if (Array.isArray(currentData)) {
|
||||
this.metadata.description = String(currentData[0] && currentData[0]["#"] || currentData[0] || "")
|
||||
.trim();
|
||||
}
|
||||
else {
|
||||
this.metadata.description = String(currentData["#"] || currentData || "").trim();
|
||||
}
|
||||
break;
|
||||
case "creator":
|
||||
if (Array.isArray(currentData)) {
|
||||
this.metadata.creator = String(currentData[0] && currentData[0]["#"] || currentData[0] || "")
|
||||
.trim();
|
||||
this.metadata.creatorFileAs = String(currentData[0] && currentData[0]['@'] && currentData[0]['@']["opf:file-as"] || this.metadata.creator)
|
||||
.trim();
|
||||
}
|
||||
else {
|
||||
this.metadata.creator = String(currentData["#"] || currentData || "").trim();
|
||||
this.metadata.creatorFileAs = String(currentData['@'] && currentData['@']["opf:file-as"] || this.metadata.creator)
|
||||
.trim();
|
||||
}
|
||||
break;
|
||||
case "date":
|
||||
if (Array.isArray(currentData)) {
|
||||
this.metadata.date = String(currentData[0] && currentData[0]["#"] || currentData[0] || "")
|
||||
.trim();
|
||||
}
|
||||
else {
|
||||
this.metadata.date = String(currentData["#"] || currentData || "").trim();
|
||||
}
|
||||
break;
|
||||
case "identifier":
|
||||
if (currentData["@"] && currentData["@"]["opf:scheme"] == "ISBN") {
|
||||
this.metadata.ISBN = String(currentData["#"] || "").trim();
|
||||
}
|
||||
else if (currentData["@"] && currentData["@"].id && currentData["@"].id.match(/uuid/i)) {
|
||||
this.metadata.UUID = String(currentData["#"] || "")
|
||||
.replace('urn:uuid:', '')
|
||||
.toUpperCase()
|
||||
.trim();
|
||||
}
|
||||
else if (Array.isArray(currentData)) {
|
||||
for (j = 0; j < currentData.length; j++) {
|
||||
if (currentData[j]["@"]) {
|
||||
if (currentData[j]["@"]["opf:scheme"] == "ISBN") {
|
||||
this.metadata.ISBN = String(currentData[j]["#"] || "").trim();
|
||||
}
|
||||
else if (currentData[j]["@"].id && currentData[j]["@"].id.match(/uuid/i)) {
|
||||
this.metadata.UUID = String(currentData[j]["#"] || "")
|
||||
.replace('urn:uuid:', '')
|
||||
.toUpperCase()
|
||||
.trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'meta':
|
||||
if (currentData['#'] && currentData['@'].property == 'calibre:author_link_map') {
|
||||
this.metadata['contribute'] = this.metadata['contribute'] || [];
|
||||
this.metadata['author_link_map'] = this.metadata['author_link_map'] || {};
|
||||
let t = JSON.parse(currentData['#']);
|
||||
for (let n in t) {
|
||||
n = n.toString().trim();
|
||||
this.metadata['contribute'].push(n);
|
||||
this.metadata['author_link_map'][n] = (t[n] || '').toString().trim();
|
||||
}
|
||||
this.metadata['contribute'] = (0, array_hyper_unique_1.array_unique)(this.metadata['contribute']);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//console.log(key, currentData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
let metas = metadata['meta'] || {};
|
||||
Object.keys(metas).forEach((key) => {
|
||||
var meta = metas[key];
|
||||
if (meta['@'] && meta['@'].name) {
|
||||
var name = meta['@'].name;
|
||||
this.metadata[name] = meta['@'].content;
|
||||
if (name == 'calibre:series') {
|
||||
this.metadata['series'] = this.metadata['series'] || meta['@'].content;
|
||||
}
|
||||
}
|
||||
if (meta['#'] && meta['@'].property) {
|
||||
this.metadata[meta['@'].property] = meta['#'];
|
||||
}
|
||||
if (meta.name && meta.name == "cover") {
|
||||
this.metadata[meta.name] = meta.content;
|
||||
}
|
||||
}, this);
|
||||
function _meta_val(row, key = null) {
|
||||
if (key !== null) {
|
||||
return row[key] || row;
|
||||
}
|
||||
return row;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* EPub#parseManifest() -> undefined
|
||||
*
|
||||
* Parses "manifest" block (all items included, html files, images, styles)
|
||||
**/
|
||||
parseManifest(manifest) {
|
||||
var i, len, path = this.rootFile.split("/"), element, path_str;
|
||||
path.pop();
|
||||
path_str = path.join("/");
|
||||
if (manifest.item) {
|
||||
for (i = 0, len = manifest.item.length; i < len; i++) {
|
||||
if (manifest.item[i]['@']) {
|
||||
element = manifest.item[i]['@'];
|
||||
element = this._Elem(element);
|
||||
if (element.href && element.href.substr(0, path_str.length) != path_str) {
|
||||
element.href = path.concat([element.href]).join("/");
|
||||
}
|
||||
this.manifest[manifest.item[i]['@'].id] = element;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* EPub#parseSpine() -> undefined
|
||||
*
|
||||
* Parses "spine" block (all html elements that are shown to the reader)
|
||||
**/
|
||||
parseSpine(spine) {
|
||||
var i, len, path = this.rootFile.split("/"), element;
|
||||
path.pop();
|
||||
if (spine['@'] && spine['@'].toc) {
|
||||
this.spine.toc = this.manifest[spine['@'].toc] || null;
|
||||
}
|
||||
if (spine.itemref) {
|
||||
if (!Array.isArray(spine.itemref)) {
|
||||
spine.itemref = [spine.itemref];
|
||||
}
|
||||
for (i = 0, len = spine.itemref.length; i < len; i++) {
|
||||
if (spine.itemref[i]['@']) {
|
||||
if (element = this.manifest[spine.itemref[i]['@'].idref]) {
|
||||
this.spine.contents.push(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.flow = this.spine.contents;
|
||||
}
|
||||
/**
|
||||
* EPub#parseTOC() -> undefined
|
||||
*
|
||||
* Parses ncx file for table of contents (title, html file)
|
||||
**/
|
||||
parseTOC() {
|
||||
var i, len, path = this.spine.toc.href.split("/"), id_list = {}, keys;
|
||||
path.pop();
|
||||
keys = Object.keys(this.manifest);
|
||||
for (i = 0, len = keys.length; i < len; i++) {
|
||||
id_list[this.manifest[keys[i]].href] = keys[i];
|
||||
}
|
||||
const xml2jsOptions = this._getStatic().xml2jsOptions;
|
||||
this.zip.readFile(this.spine.toc.href, (err, data) => {
|
||||
if (err) {
|
||||
this.emit("error", new Error("Reading archive failed"));
|
||||
return;
|
||||
}
|
||||
var xml = data.toString("utf-8"), xmlparser = new xml2js_1.default.Parser(xml2jsOptions);
|
||||
xmlparser.on("end", (result) => {
|
||||
if (result.navMap && result.navMap.navPoint) {
|
||||
this.toc = this.walkNavMap(result.navMap.navPoint, path, id_list);
|
||||
}
|
||||
this.emit("end");
|
||||
});
|
||||
xmlparser.on("error", (err) => {
|
||||
this.emit("error", new Error("Parsing container XML failed"));
|
||||
return;
|
||||
});
|
||||
xmlparser.parseString(xml);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* EPub#walkNavMap(branch, path, id_list,[, level]) -> Array
|
||||
* - branch (Array | Object): NCX NavPoint object
|
||||
* - path (Array): Base path
|
||||
* - id_list (Object): map of file paths and id values
|
||||
* - level (Number): deepness
|
||||
*
|
||||
* Walks the NavMap object through all levels and finds elements
|
||||
* for TOC
|
||||
**/
|
||||
walkNavMap(branch, path, id_list, level, pe, parentNcx, ncx_idx) {
|
||||
ncx_idx = ncx_idx || {
|
||||
index: 0,
|
||||
};
|
||||
level = level || 0;
|
||||
this.ncx_depth = Math.max(level + 1, this.ncx_depth || 0);
|
||||
// don't go too far
|
||||
if (level > 7) {
|
||||
return [];
|
||||
}
|
||||
var output = [];
|
||||
if (!Array.isArray(branch)) {
|
||||
branch = [branch];
|
||||
}
|
||||
this.ncx = this.ncx || [];
|
||||
for (var i = 0; i < branch.length; i++) {
|
||||
let element;
|
||||
let currentNcx;
|
||||
if (branch[i].navLabel) {
|
||||
var title = '';
|
||||
if (branch[i].navLabel && typeof branch[i].navLabel.text == 'string') {
|
||||
/*
|
||||
title = branch[i].navLabel && branch[i].navLabel.text || branch[i].navLabel === branch[i].navLabel
|
||||
? ''
|
||||
: (branch[i].navLabel && branch[i].navLabel.text || branch[i].navLabel || "").trim();
|
||||
*/
|
||||
title = String(branch[i].navLabel && branch[i].navLabel.text || branch[i].navLabel || "").trim();
|
||||
}
|
||||
var order = Number(branch[i]["@"] && branch[i]["@"].playOrder || 0);
|
||||
if (isNaN(order)) {
|
||||
order = 0;
|
||||
}
|
||||
var href = '';
|
||||
if (branch[i].content && branch[i].content["@"] && typeof branch[i].content["@"].src == 'string') {
|
||||
href = branch[i].content["@"].src.trim();
|
||||
}
|
||||
element = {
|
||||
level: level,
|
||||
order: order,
|
||||
title: title
|
||||
};
|
||||
if (href) {
|
||||
href = path.concat([href]).join("/");
|
||||
element.href = href;
|
||||
if (id_list[element.href]) {
|
||||
// link existing object
|
||||
element = this.manifest[id_list[element.href]];
|
||||
element.title = title;
|
||||
element.order = order;
|
||||
element.level = level;
|
||||
}
|
||||
else {
|
||||
// use new one
|
||||
element.href = href;
|
||||
element.id = (branch[i]["@"] && branch[i]["@"].id || "").trim();
|
||||
}
|
||||
if (level == 0) {
|
||||
let idx = this.ncx.length;
|
||||
currentNcx = this.ncx[idx] = {
|
||||
id: element.id,
|
||||
ncx_index: idx,
|
||||
ncx_index2: ncx_idx.index++,
|
||||
level,
|
||||
sub: [],
|
||||
};
|
||||
}
|
||||
else if (parentNcx) {
|
||||
let idx = parentNcx.sub.length;
|
||||
currentNcx = parentNcx.sub[parentNcx.sub.length] = {
|
||||
id: element.id,
|
||||
ncx_index: idx,
|
||||
ncx_index2: ncx_idx.index++,
|
||||
level,
|
||||
sub: [],
|
||||
};
|
||||
}
|
||||
output.push(element);
|
||||
}
|
||||
}
|
||||
//console.log(ncx_idx);
|
||||
if (branch[i].navPoint) {
|
||||
output = output.concat(this.walkNavMap(branch[i].navPoint, path, id_list, level + 1, element, currentNcx, ncx_idx));
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
/**
|
||||
* EPub#getChapter(id, callback) -> undefined
|
||||
* - id (String): Manifest id value for a chapter
|
||||
* - callback (Function): callback function
|
||||
*
|
||||
* Finds a chapter text for an id. Replaces image and link URL's, removes
|
||||
* <head> etc. elements. Return only chapters with mime type application/xhtml+xml
|
||||
**/
|
||||
getChapter(chapterId, callback) {
|
||||
let self = this;
|
||||
this.getChapterRaw(chapterId, (err, str) => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
let meta = self.manifest[chapterId];
|
||||
var i, len, path = this.rootFile.split("/"), keys = Object.keys(this.manifest);
|
||||
path.pop();
|
||||
let basePath = (0, path_1.dirname)(meta.href);
|
||||
let baseHref = meta.href;
|
||||
// remove linebreaks (no multi line matches in JS regex!)
|
||||
str = str.replace(/\r?\n/g, "\u0000");
|
||||
// keep only <body> contents
|
||||
// @ts-ignore
|
||||
str.replace(/<body[^>]*?>(.*)<\/body[^>]*?>/i, function (o, d) {
|
||||
str = d.trim();
|
||||
});
|
||||
// remove <script> blocks if any
|
||||
str = str.replace(/<script[^>]*?>(.*?)<\/script[^>]*?>/ig, function (o, s) {
|
||||
return "";
|
||||
});
|
||||
// remove <style> blocks if any
|
||||
str = str.replace(/<style[^>]*?>(.*?)<\/style[^>]*?>/ig, function (o, s) {
|
||||
return "";
|
||||
});
|
||||
// remove onEvent handlers
|
||||
str = str.replace(/(\s)(on\w+)(\s*=\s*["']?[^"'\s>]*?["'\s>])/g, function (o, a, b, c) {
|
||||
return a + "skip-" + b + c;
|
||||
});
|
||||
// replace images
|
||||
str = str.replace(/(?<=\s|^)(src\s*=\s*)(["']?)([^"'\n]*?)(\2)/g, (o, a, d, b, c) => {
|
||||
let img = path_1.posix.join(basePath, b);
|
||||
let element;
|
||||
for (i = 0, len = keys.length; i < len; i++) {
|
||||
let _arr = [
|
||||
self.manifest[keys[i]].href,
|
||||
decodeURI(self.manifest[keys[i]].href),
|
||||
encodeURI(self.manifest[keys[i]].href),
|
||||
];
|
||||
if (_arr.includes(img)) {
|
||||
element = self.manifest[keys[i]];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (element) {
|
||||
let s = a + d + (0, url_1.resolve)(this.imageroot, img) + c;
|
||||
return s;
|
||||
}
|
||||
return o;
|
||||
});
|
||||
/*
|
||||
str = str.replace(/(\ssrc\s*=\s*["']?)([^"'\s>]*?)(["'\s>])/g, (function (o, a, b, c)
|
||||
{
|
||||
var img = path.concat([b]).join("/").trim(),
|
||||
element;
|
||||
|
||||
for (i = 0, len = keys.length; i < len; i++)
|
||||
{
|
||||
if (this.manifest[keys[i]].href == img)
|
||||
{
|
||||
element = this.manifest[keys[i]];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// include only images from manifest
|
||||
if (element)
|
||||
{
|
||||
return a + this.imageroot + element.id + "/" + img + c;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
}).bind(this));
|
||||
*/
|
||||
// replace links
|
||||
str = str.replace(/(\shref\s*=\s*["']?)([^"'\s>]*?)(["'\s>])/g, (o, a, b, c) => {
|
||||
var linkparts = b && b.split("#"), link = path.concat([(linkparts.shift() || "")]).join("/").trim(), element;
|
||||
for (i = 0, len = keys.length; i < len; i++) {
|
||||
if (this.manifest[keys[i]].href.split("#")[0] == link) {
|
||||
element = this.manifest[keys[i]];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (linkparts.length) {
|
||||
link += "#" + linkparts.join("#");
|
||||
}
|
||||
// include only images from manifest
|
||||
if (element) {
|
||||
return a + this.linkroot + element.id + "/" + link + c;
|
||||
}
|
||||
else {
|
||||
return a + b + c;
|
||||
}
|
||||
});
|
||||
// bring back linebreaks
|
||||
str = str.replace(/\u0000/g, "\n").trim();
|
||||
callback(null, str);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* EPub#getChapterRaw(id, callback) -> undefined
|
||||
* - id (String): Manifest id value for a chapter
|
||||
* - callback (Function): callback function
|
||||
*
|
||||
* Returns the raw chapter text for an id.
|
||||
**/
|
||||
getChapterRaw(chapterId, callback) {
|
||||
if (this.manifest[chapterId]) {
|
||||
if (!(this.manifest[chapterId]['media-type'] == "application/xhtml+xml" || this.manifest[chapterId]['media-type'] == "image/svg+xml")) {
|
||||
return callback(new Error(`Invalid mime type for chapter "${chapterId}" ${this.manifest[chapterId]['media-type']}`));
|
||||
}
|
||||
this.zip.readFile(this.manifest[chapterId].href, (function (err, data) {
|
||||
if (err) {
|
||||
callback(new Error(`Reading archive failed "${chapterId}", ${this.manifest[chapterId].href}`));
|
||||
return;
|
||||
}
|
||||
else if (!data) {
|
||||
callback(new Error(`Reading archive failed "${chapterId}", ${this.manifest[chapterId].href}`));
|
||||
return;
|
||||
}
|
||||
callback(null, (0, crlf_normalize_1.crlf)(data.toString("utf-8")));
|
||||
}).bind(this));
|
||||
}
|
||||
else {
|
||||
callback(new Error(`File not found "${chapterId}"`));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* EPub#getImage(id, callback) -> undefined
|
||||
* - id (String): Manifest id value for an image
|
||||
* - callback (Function): callback function
|
||||
*
|
||||
* Finds an image for an id. Returns the image as Buffer. Callback gets
|
||||
* an error object, image buffer and image content-type.
|
||||
* Return only images with mime type image
|
||||
**/
|
||||
getImage(id, callback) {
|
||||
if (this.manifest[id]) {
|
||||
if ((this.manifest[id]['media-type'] || "").toLowerCase().trim().substr(0, 6) != "image/") {
|
||||
return callback(new Error("Invalid mime type for image"));
|
||||
}
|
||||
this.getFile(id, callback);
|
||||
}
|
||||
else {
|
||||
callback(new Error("File not found"));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* EPub#getFile(id, callback) -> undefined
|
||||
* - id (String): Manifest id value for a file
|
||||
* - callback (Function): callback function
|
||||
*
|
||||
* Finds a file for an id. Returns the file as Buffer. Callback gets
|
||||
* an error object, file contents buffer and file content-type.
|
||||
**/
|
||||
getFile(id, callback) {
|
||||
if (this.manifest[id]) {
|
||||
let self = this;
|
||||
this.zip.readFile(this.manifest[id].href, (err, data) => {
|
||||
if (err) {
|
||||
callback(new Error(`Reading archive failed ${self.manifest[id].href}`));
|
||||
return;
|
||||
}
|
||||
callback(null, data, this.manifest[id]['media-type']);
|
||||
});
|
||||
}
|
||||
else {
|
||||
callback(new RangeError(`File not found "${id}"`));
|
||||
}
|
||||
}
|
||||
readFile(filename, options, callback_) {
|
||||
let callback = arguments[arguments.length - 1];
|
||||
if (typeof options === 'function' || !options) {
|
||||
this.zip.readFile(filename, callback);
|
||||
}
|
||||
else if (typeof options === 'string') {
|
||||
// options is an encoding
|
||||
this.zip.readFile(filename, function (err, data) {
|
||||
if (err) {
|
||||
callback(new Error(`Reading archive failed ${filename}`));
|
||||
return;
|
||||
}
|
||||
callback(null, data.toString(options));
|
||||
});
|
||||
}
|
||||
else {
|
||||
throw new TypeError('Bad arguments');
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.EPub = EPub;
|
||||
EPub.SYMBOL_RAW_DATA = types_1.SYMBOL_RAW_DATA;
|
||||
EPub.IMAGE_ROOT = '/images/';
|
||||
EPub.LINK_ROOT = '/links/';
|
||||
EPub.ELEM_MEDIA_TYPE = 'media-type';
|
||||
EPub.ELEM_MEDIA_TYPE2 = 'mediaType';
|
||||
EPub.xml2jsOptions = Object.assign({}, xml2js_1.default.defaults['0.1']);
|
||||
exports.default = EPub;
|
||||
//# sourceMappingURL=epub.js.map
|
||||
File diff suppressed because one or more lines are too long
Vendored
+57
@@ -0,0 +1,57 @@
|
||||
import { SYMBOL_RAW_DATA } from '../types';
|
||||
export interface TocElement {
|
||||
level?: number;
|
||||
order?: number;
|
||||
title?: string;
|
||||
id?: string;
|
||||
href?: string;
|
||||
'media-type'?: string;
|
||||
mediaType?: string;
|
||||
'epub-type'?: string;
|
||||
lang?: string;
|
||||
series?: string;
|
||||
contribute?: string[];
|
||||
author_link_map?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
}
|
||||
export interface ISpine {
|
||||
contents: ISpineContents;
|
||||
toc?: TocElement;
|
||||
itemref?: Object[];
|
||||
}
|
||||
export interface IMetadataList {
|
||||
[key: string]: TocElement;
|
||||
}
|
||||
export interface ISpineContents extends Array<TocElement> {
|
||||
[index: number]: TocElement;
|
||||
}
|
||||
export interface IMetadata {
|
||||
publisher?: string;
|
||||
language?: string;
|
||||
title?: string;
|
||||
subject?: string[];
|
||||
description?: string;
|
||||
creator?: string;
|
||||
creatorFileAs?: string;
|
||||
date?: string;
|
||||
ISBN?: string;
|
||||
UUID?: string;
|
||||
cover?: any;
|
||||
'file-as'?: string;
|
||||
'belongs-to-collection'?: string;
|
||||
'calibre:series'?: string;
|
||||
'collection-type'?: string;
|
||||
[key: string]: any;
|
||||
[SYMBOL_RAW_DATA]?: IMetadata;
|
||||
}
|
||||
export interface INcx extends Array<INcxTree> {
|
||||
[index: number]: INcxTree;
|
||||
}
|
||||
export interface INcxTree {
|
||||
id: string;
|
||||
ncx_index: number;
|
||||
ncx_index2?: number;
|
||||
level?: number;
|
||||
sub: INcxTree[];
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const types_1 = require("../types");
|
||||
//# sourceMappingURL=const.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"const.js","sourceRoot":"","sources":["const.ts"],"names":[],"mappings":";;AAAA,oCAA2C","sourcesContent":["import { SYMBOL_RAW_DATA } from '../types';\n\nexport interface TocElement\n{\n\tlevel?: number;\n\torder?: number;\n\ttitle?: string;\n\tid?: string;\n\thref?: string;\n\n\t'media-type'?: string,\n\tmediaType?: string,\n\t'epub-type'?: string,\n\tlang?: string,\n\n\tseries?: string,\n\n\tcontribute?: string[],\n\tauthor_link_map?: {\n\t\t[key: string]: string,\n\t}\n}\n\nexport interface ISpine\n{\n\tcontents: ISpineContents,\n\ttoc?: TocElement,\n\n\titemref?: Object[],\n}\n\nexport interface IMetadataList\n{\n\t[key: string]: TocElement,\n}\n\nexport interface ISpineContents extends Array<TocElement>\n{\n\t[index: number]: TocElement,\n}\n\nexport interface IMetadata\n{\n\tpublisher?: string,\n\tlanguage?: string,\n\ttitle?: string,\n\tsubject?: string[],\n\tdescription?: string,\n\n\tcreator?: string,\n\tcreatorFileAs?: string,\n\n\tdate?: string,\n\tISBN?: string,\n\tUUID?: string,\n\tcover?\n\n\t'file-as'?: string,\n\n\t'belongs-to-collection'?: string,\n\t'calibre:series'?: string,\n\t'collection-type'?: string,\n\n\t[key: string]: any,\n\n\t[SYMBOL_RAW_DATA]?: IMetadata,\n}\n\nexport interface INcx extends Array<INcxTree>\n{\n\t[index: number]: INcxTree\n}\n\nexport interface INcxTree\n{\n\tid: string;\n\tncx_index: number;\n\tncx_index2?: number;\n\tlevel?: number;\n\tsub: INcxTree[],\n}\n"]}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
/// <reference types="node" />
|
||||
export declare function isEpub(data: string, buf?: boolean): string;
|
||||
export declare function isEpub(data: Buffer, buf?: boolean): Buffer;
|
||||
export declare function isEpub(data: any, buf?: boolean): any;
|
||||
@@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isEpub = void 0;
|
||||
function isEpub(data, buf) {
|
||||
let txt = (typeof data == 'string' && !buf) ? data : data.toString("utf-8").toLowerCase().trim();
|
||||
if (txt === 'application/epub+zip') {
|
||||
return data;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
exports.isEpub = isEpub;
|
||||
//# sourceMappingURL=isEpub.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"isEpub.js","sourceRoot":"","sources":["isEpub.ts"],"names":[],"mappings":";;;AAGA,SAAgB,MAAM,CAAC,IAAI,EAAE,GAAa;IAEzC,IAAI,GAAG,GAAG,CAAC,OAAO,IAAI,IAAI,QAAQ,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAEjG,IAAI,GAAG,KAAK,sBAAsB,EAClC;QACC,OAAO,IAAI,CAAC;KACZ;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAVD,wBAUC","sourcesContent":["export function isEpub(data: string, buf?: boolean): string\nexport function isEpub(data: Buffer, buf?: boolean): Buffer\nexport function isEpub(data, buf?: boolean)\nexport function isEpub(data, buf?: boolean)\n{\n\tlet txt = (typeof data == 'string' && !buf) ? data : data.toString(\"utf-8\").toLowerCase().trim();\n\n\tif (txt === 'application/epub+zip')\n\t{\n\t\treturn data;\n\t}\n\n\treturn null;\n}\n"]}
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Created by user on 2018/3/18/018.
|
||||
*/
|
||||
import { EPub } from '../index';
|
||||
import { EPub as libEPub } from './epub';
|
||||
export declare function fixToc(epub: EPub | libEPub): libEPub | EPub;
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Created by user on 2018/3/18/018.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.fixToc = void 0;
|
||||
function fixToc(epub) {
|
||||
let manifest_keys = Object.keys(epub.manifest);
|
||||
if (!epub.toc.length) {
|
||||
epub.toc = Object.values(epub.manifest).filter(node => {
|
||||
if (['text/css', 'application/x-dtbncx+xml'].includes(node.mediaType)
|
||||
|| /^(image)/.test(node.mediaType)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return epub;
|
||||
}
|
||||
epub.toc.forEach(function (toc, idx) {
|
||||
if (!epub.manifest[toc.id]) {
|
||||
for (let k of manifest_keys) {
|
||||
let row = epub.manifest[k];
|
||||
if ((row.href == toc.href) || (row.href.replace(/#.+$/g, '') == toc.href.replace(/#.+$/g, ''))) {
|
||||
toc.id = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return epub;
|
||||
}
|
||||
exports.fixToc = fixToc;
|
||||
//# sourceMappingURL=toc.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"toc.js","sourceRoot":"","sources":["toc.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAKH,SAAgB,MAAM,CAAC,IAAoB;IAE1C,IAAI,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAE/C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EACpB;QACC,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;YAErD,IACC,CAAC,UAAU,EAAE,0BAA0B,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC;mBAC9D,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAEnC;gBACC,OAAO,KAAK,CAAC;aACb;YAED,OAAO,IAAI,CAAC;QACb,CAAC,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC;KACZ;IAED,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,GAAG,EAAE,GAAG;QAElC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAC1B;YACC,KAAK,IAAI,CAAC,IAAI,aAAa,EAC3B;gBACC,IAAI,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBAE3B,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAC9F;oBACC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;iBACX;aACD;SACD;IACF,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AACb,CAAC;AAvCD,wBAuCC","sourcesContent":["/**\n * Created by user on 2018/3/18/018.\n */\n\nimport { EPub } from '../index';\nimport { EPub as libEPub } from './epub';\n\nexport function fixToc(epub: EPub | libEPub)\n{\n\tlet manifest_keys = Object.keys(epub.manifest);\n\n\tif (!epub.toc.length)\n\t{\n\t\tepub.toc = Object.values(epub.manifest).filter(node => {\n\n\t\t\tif (\n\t\t\t\t['text/css', 'application/x-dtbncx+xml'].includes(node.mediaType)\n\t\t\t\t|| /^(image)/.test(node.mediaType)\n\t\t\t)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t});\n\n\t\treturn epub;\n\t}\n\n\tepub.toc.forEach(function (toc, idx)\n\t{\n\t\tif (!epub.manifest[toc.id])\n\t\t{\n\t\t\tfor (let k of manifest_keys)\n\t\t\t{\n\t\t\t\tlet row = epub.manifest[k];\n\n\t\t\t\tif ((row.href == toc.href) || (row.href.replace(/#.+$/g, '') == toc.href.replace(/#.+$/g, '')))\n\t\t\t\t{\n\t\t\t\t\ttoc.id = k;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\treturn epub;\n}\n"]}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Created by user on 2020/6/10.
|
||||
*/
|
||||
export declare const SYMBOL_RAW_DATA: unique symbol;
|
||||
@@ -0,0 +1,8 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Created by user on 2020/6/10.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SYMBOL_RAW_DATA = void 0;
|
||||
exports.SYMBOL_RAW_DATA = Symbol.for('rawData');
|
||||
//# sourceMappingURL=types.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEU,QAAA,eAAe,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC","sourcesContent":["/**\n * Created by user on 2020/6/10.\n */\n\nexport const SYMBOL_RAW_DATA = Symbol.for('rawData');\n\n"]}
|
||||
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"name": "epub2",
|
||||
"version": "3.0.2",
|
||||
"description": "Parse ePub electronic book files with Node.JS",
|
||||
"keywords": [
|
||||
"archive",
|
||||
"async",
|
||||
"book",
|
||||
"books",
|
||||
"chapter",
|
||||
"comic",
|
||||
"epub",
|
||||
"epub-maker",
|
||||
"epub-maker2",
|
||||
"extract",
|
||||
"file",
|
||||
"image",
|
||||
"manifest",
|
||||
"metadata",
|
||||
"mobile",
|
||||
"node-novel",
|
||||
"novel",
|
||||
"parse",
|
||||
"promise",
|
||||
"raw",
|
||||
"volume",
|
||||
"zip"
|
||||
],
|
||||
"homepage": "https://github.com/bluelovers/ws-epub/tree/master/packages/epub2#readme",
|
||||
"bugs": {
|
||||
"url": "https://github.com/bluelovers/ws-epub/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/bluelovers/ws-epub.git",
|
||||
"directory": "packages/epub2"
|
||||
},
|
||||
"license": "ISC",
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "http://github.com/julien-c/epub/blob/master/LICENSE"
|
||||
}
|
||||
],
|
||||
"author": "Andris Reinman",
|
||||
"contributors": [
|
||||
"andris <andris@node.ee>",
|
||||
"Julien Chaumond <chaumond@gmail.com> (https://github.com/julien-c)"
|
||||
],
|
||||
"main": "./index",
|
||||
"typings": "./index.d.ts",
|
||||
"directories": {
|
||||
"lib": "lib",
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"coverage": "yarn run test -- --coverage",
|
||||
"test": "echo \"Error: no test specified\"",
|
||||
"test:jest": "jest --passWithNoTests",
|
||||
"test:jest:snapshot": "yarn run test:jest -- -u",
|
||||
"test:snapshot": "yarn run test -- -u",
|
||||
"test:tsd": "ynpx tsd",
|
||||
"preversion": "yarn run test"
|
||||
},
|
||||
"dependencies": {
|
||||
"adm-zip": "^0.5.10",
|
||||
"array-hyper-unique": "^2.1.4",
|
||||
"bluebird": "^3.7.2",
|
||||
"crlf-normalize": "^1.0.19",
|
||||
"tslib": "^2.6.2",
|
||||
"xml2js": "^0.6.2"
|
||||
},
|
||||
"engine": [
|
||||
"node >=0.3.0"
|
||||
],
|
||||
"gitHead": "d27ef52af34a27b1f18b4fc3a101850638c7bb38"
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@types/node@*":
|
||||
version "24.10.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-24.10.1.tgz#91e92182c93db8bd6224fca031e2370cef9a8f01"
|
||||
integrity sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==
|
||||
dependencies:
|
||||
undici-types "~7.16.0"
|
||||
|
||||
adm-zip@^0.5.10:
|
||||
version "0.5.16"
|
||||
resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.16.tgz#0b5e4c779f07dedea5805cdccb1147071d94a909"
|
||||
integrity sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==
|
||||
|
||||
array-hyper-unique@^2.1.4:
|
||||
version "2.1.6"
|
||||
resolved "https://registry.yarnpkg.com/array-hyper-unique/-/array-hyper-unique-2.1.6.tgz#429412fd63b7bd7c920f6cdbf60d1dd292855b2e"
|
||||
integrity sha512-BdlHRqjKSYs88WFaVNVEc6Kv8ln/FdzCKPbcDPuWs4/EXkQFhnjc8TyR7hnPxRjcjo5LKOhUMGUWpAqRgeJvpA==
|
||||
dependencies:
|
||||
deep-eql "= 4.0.0"
|
||||
lodash "^4.17.21"
|
||||
|
||||
bluebird@^3.7.2:
|
||||
version "3.7.2"
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
|
||||
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
|
||||
|
||||
crlf-normalize@^1.0.19:
|
||||
version "1.0.20"
|
||||
resolved "https://registry.yarnpkg.com/crlf-normalize/-/crlf-normalize-1.0.20.tgz#0b3105d3de807bce8a7599113235d725fe9361a8"
|
||||
integrity sha512-h/rBerTd3YHQGfv7tNT25mfhWvRq2BBLCZZ80GFarFxf6HQGbpW6iqDL3N+HBLpjLfAdcBXfWAzVlLfHkRUQBQ==
|
||||
dependencies:
|
||||
ts-type ">=2"
|
||||
|
||||
"deep-eql@= 4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.0.0.tgz#c70af2713a4e18d9c2c1203ff9d11abbd51c8fbd"
|
||||
integrity sha512-GxJC5MOg2KyQlv6WiUF/VAnMj4MWnYiXo4oLgeptOELVoknyErb4Z8+5F/IM/K4g9/80YzzatxmWcyRwUseH0A==
|
||||
dependencies:
|
||||
type-detect "^4.0.0"
|
||||
|
||||
epub2@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/epub2/-/epub2-3.0.2.tgz#eee764e2b6b965d36c7713736bd49f6941d8c9c4"
|
||||
integrity sha512-rhvpt27CV5MZfRetfNtdNwi3XcNg1Am0TwfveJkK8YWeHItHepQ8Js9J06v8XRIjuTrCW/NSGYMTy55Of7BfNQ==
|
||||
dependencies:
|
||||
adm-zip "^0.5.10"
|
||||
array-hyper-unique "^2.1.4"
|
||||
bluebird "^3.7.2"
|
||||
crlf-normalize "^1.0.19"
|
||||
tslib "^2.6.2"
|
||||
xml2js "^0.6.2"
|
||||
|
||||
lodash@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
||||
sax@>=0.6.0:
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.3.tgz#fcebae3b756cdc8428321805f4b70f16ec0ab5db"
|
||||
integrity sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==
|
||||
|
||||
ts-type@>=2:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ts-type/-/ts-type-3.0.1.tgz#b52e7623065e0beb43c77c426347d85cf81dff84"
|
||||
integrity sha512-cleRydCkBGBFQ4KAvLH0ARIkciduS745prkGVVxPGvcRGhMMoSJUB7gNR1ByKhFTEYrYRg2CsMRGYnqp+6op+g==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
tslib ">=2"
|
||||
typedarray-dts "^1.0.0"
|
||||
|
||||
tslib@>=2, tslib@^2.6.2:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
|
||||
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
|
||||
|
||||
type-detect@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.1.0.tgz#deb2453e8f08dcae7ae98c626b13dddb0155906c"
|
||||
integrity sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==
|
||||
|
||||
typedarray-dts@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/typedarray-dts/-/typedarray-dts-1.0.0.tgz#9dec9811386dbfba964c295c2606cf9a6b982d06"
|
||||
integrity sha512-Ka0DBegjuV9IPYFT1h0Qqk5U4pccebNIJCGl8C5uU7xtOs+jpJvKGAY4fHGK25hTmXZOEUl9Cnsg5cS6K/b5DA==
|
||||
|
||||
undici-types@~7.16.0:
|
||||
version "7.16.0"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46"
|
||||
integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==
|
||||
|
||||
xml2js@^0.6.2:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499"
|
||||
integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==
|
||||
dependencies:
|
||||
sax ">=0.6.0"
|
||||
xmlbuilder "~11.0.0"
|
||||
|
||||
xmlbuilder@~11.0.0:
|
||||
version "11.0.1"
|
||||
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
|
||||
integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Created by user on 2018/2/1/001.
|
||||
*/
|
||||
/// <reference types="node" />
|
||||
export declare let ZipFile: IZipFile;
|
||||
export interface IZipFile {
|
||||
names: string[];
|
||||
count: number;
|
||||
constructor(filename: string): any;
|
||||
readFile(name: string, cb: (error: any, buffer: Buffer) => void): void;
|
||||
}
|
||||
export default ZipFile;
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Created by user on 2018/2/1/001.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ZipFile = void 0;
|
||||
try {
|
||||
// zipfile is an optional dependency:
|
||||
exports.ZipFile = require("zipfile").ZipFile;
|
||||
}
|
||||
catch (err) {
|
||||
// Mock zipfile using pure-JS adm-zip:
|
||||
const AdmZip = require('adm-zip');
|
||||
// @ts-ignore
|
||||
exports.ZipFile = (class {
|
||||
constructor(filename) {
|
||||
this.admZip = new AdmZip(filename);
|
||||
this.names = this.admZip.getEntries().map(function (zipEntry) {
|
||||
return zipEntry.entryName;
|
||||
});
|
||||
}
|
||||
readFile(name, cb) {
|
||||
this.admZip.readFileAsync(this.admZip.getEntry(name), (buffer, error) => {
|
||||
if (error || !buffer) {
|
||||
name = decodeURIComponent(name);
|
||||
this.admZip.readFileAsync(this.admZip.getEntry(name), (buffer, error) => cb(error, buffer));
|
||||
}
|
||||
else {
|
||||
cb(error, buffer);
|
||||
}
|
||||
});
|
||||
}
|
||||
get count() {
|
||||
return this.names.length;
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.default = exports.ZipFile;
|
||||
//# sourceMappingURL=zipfile.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"zipfile.js","sourceRoot":"","sources":["zipfile.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAYH,IACA;IACC,qCAAqC;IACrC,eAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC;CACrC;AACD,OAAO,GAAG,EACV;IACC,sCAAsC;IACtC,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAElC,aAAa;IACb,eAAO,GAAG,CAAC;QAKV,YAAY,QAAgB;YAE3B,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC;YACnC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,UAAU,QAAQ;gBAE3D,OAAO,QAAQ,CAAC,SAAS,CAAC;YAC3B,CAAC,CAAC,CAAC;QACJ,CAAC;QAEM,QAAQ,CAAC,IAAY,EAAE,EAA2B;YAExD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;gBAEvE,IAAI,KAAK,IAAI,CAAC,MAAM,EACpB;oBACC,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;oBAEhC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;iBAC5F;qBAED;oBACC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;iBAClB;YACF,CAAC,CAAC,CAAC;QACJ,CAAC;QAED,IAAW,KAAK;YAEf,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QAC1B,CAAC;KACD,CAAC,CAAC;CACH;AAED,kBAAe,eAAO,CAAC","sourcesContent":["/**\n * Created by user on 2018/2/1/001.\n */\n\nexport let ZipFile: IZipFile;\n\nexport interface IZipFile\n{\n\tnames: string[];\n\tcount: number;\n\tconstructor(filename: string);\n\treadFile(name: string, cb: (error, buffer: Buffer) => void): void;\n}\n\ntry\n{\n\t// zipfile is an optional dependency:\n\tZipFile = require(\"zipfile\").ZipFile;\n}\ncatch (err)\n{\n\t// Mock zipfile using pure-JS adm-zip:\n\tconst AdmZip = require('adm-zip');\n\n\t// @ts-ignore\n\tZipFile = (class\n\t{\n\t\tprotected admZip;\n\t\tpublic names: string[];\n\n\t\tconstructor(filename: string)\n\t\t{\n\t\t\tthis.admZip = new AdmZip(filename);\n\t\t\tthis.names = this.admZip.getEntries().map(function (zipEntry)\n\t\t\t{\n\t\t\t\treturn zipEntry.entryName;\n\t\t\t});\n\t\t}\n\n\t\tpublic readFile(name: string, cb: (error, buffer) => void)\n\t\t{\n\t\t\tthis.admZip.readFileAsync(this.admZip.getEntry(name), (buffer, error) =>\n\t\t\t{\n\t\t\t\tif (error || !buffer)\n\t\t\t\t{\n\t\t\t\t\tname = decodeURIComponent(name);\n\n\t\t\t\t\tthis.admZip.readFileAsync(this.admZip.getEntry(name), (buffer, error) => cb(error, buffer));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tcb(error, buffer);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tpublic get count(): number\n\t\t{\n\t\t\treturn this.names.length;\n\t\t}\n\t});\n}\n\nexport default ZipFile;\n"]}
|
||||
Reference in New Issue
Block a user