3.0.2 pin+patch

This commit is contained in:
Timothy Carambat
2025-11-26 17:06:27 -08:00
commit 9df68c0041
28 changed files with 1692 additions and 0 deletions
+16
View File
@@ -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.
+158
View File
@@ -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;
```
Vendored
+2
View File
@@ -0,0 +1,2 @@
import { EPub } from './lib/epub';
export = EPub;
+44
View File
@@ -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
+1
View File
@@ -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
View File
@@ -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;
+93
View File
@@ -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
+1
View File
File diff suppressed because one or more lines are too long
+175
View File
@@ -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
View File
@@ -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
+1
View File
File diff suppressed because one or more lines are too long
+57
View File
@@ -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[];
}
+4
View File
@@ -0,0 +1,4 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const types_1 = require("../types");
//# sourceMappingURL=const.js.map
+1
View File
@@ -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"]}
+4
View File
@@ -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;
+12
View File
@@ -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
+1
View File
@@ -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"]}
+6
View File
@@ -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
View File
@@ -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
+1
View File
@@ -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"]}
+4
View File
@@ -0,0 +1,4 @@
/**
* Created by user on 2020/6/10.
*/
export declare const SYMBOL_RAW_DATA: unique symbol;
+8
View File
@@ -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
+1
View File
@@ -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"]}
+77
View File
@@ -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"
}
+106
View File
@@ -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==
+12
View File
@@ -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
View File
@@ -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
+1
View File
@@ -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"]}