diff --git a/.gitignore b/.gitignore index dfc4e8f..c07f0c7 100644 --- a/.gitignore +++ b/.gitignore @@ -125,6 +125,3 @@ Icon Network Trash Folder Temporary Items .apdisk - -# Build-related directories -dist/ diff --git a/dist/jepub.js b/dist/jepub.js new file mode 100644 index 0000000..894ef3b --- /dev/null +++ b/dist/jepub.js @@ -0,0 +1,1708 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define("jEpub", [], factory); + else if(typeof exports === 'object') + exports["jEpub"] = factory(); + else + root["jEpub"] = factory(); +})(self, () => { +return /******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ "./node_modules/@babel/runtime/helpers/interopRequireDefault.js": +/*!**********************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/interopRequireDefault.js ***! + \**********************************************************************/ +/***/ ((module) => { + +function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + "default": obj + }; +} + +module.exports = _interopRequireDefault; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/interopRequireWildcard.js": +/*!***********************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/interopRequireWildcard.js ***! + \***********************************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var _typeof = __webpack_require__(/*! ../helpers/typeof */ "./node_modules/@babel/runtime/helpers/typeof.js"); + +function _getRequireWildcardCache() { + if (typeof WeakMap !== "function") return null; + var cache = new WeakMap(); + + _getRequireWildcardCache = function _getRequireWildcardCache() { + return cache; + }; + + return cache; +} + +function _interopRequireWildcard(obj) { + if (obj && obj.__esModule) { + return obj; + } + + if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { + return { + "default": obj + }; + } + + var cache = _getRequireWildcardCache(); + + if (cache && cache.has(obj)) { + return cache.get(obj); + } + + var newObj = {}; + var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; + + for (var key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; + + if (desc && (desc.get || desc.set)) { + Object.defineProperty(newObj, key, desc); + } else { + newObj[key] = obj[key]; + } + } + } + + newObj["default"] = obj; + + if (cache) { + cache.set(obj, newObj); + } + + return newObj; +} + +module.exports = _interopRequireWildcard; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/typeof.js": +/*!*******************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/typeof.js ***! + \*******************************************************/ +/***/ ((module) => { + +function _typeof(obj) { + "@babel/helpers - typeof"; + + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + module.exports = _typeof = function _typeof(obj) { + return typeof obj; + }; + } else { + module.exports = _typeof = function _typeof(obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); +} + +module.exports = _typeof; + +/***/ }), + +/***/ "./src/jepub.js": +/*!**********************!*\ + !*** ./src/jepub.js ***! + \**********************/ +/***/ ((module, exports, __webpack_require__) => { + +"use strict"; + + +var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "./node_modules/@babel/runtime/helpers/interopRequireDefault.js"); + +var _interopRequireWildcard = __webpack_require__(/*! @babel/runtime/helpers/interopRequireWildcard */ "./node_modules/@babel/runtime/helpers/interopRequireWildcard.js"); + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var utils = _interopRequireWildcard(__webpack_require__(/*! ./utils */ "./src/utils.js")); + +var _imageType = _interopRequireDefault(__webpack_require__(/*! image-type */ "./node_modules/image-type/index.js")); + +var _i18n = _interopRequireDefault(__webpack_require__(/*! ./i18n.json */ "./src/i18n.json")); + +var _container = _interopRequireDefault(__webpack_require__(/*! ./tpl/epub/META-INF/container.xml */ "./src/tpl/epub/META-INF/container.xml")); + +var _frontCover = _interopRequireDefault(__webpack_require__(/*! ./tpl/epub/OEBPS/front-cover.html */ "./src/tpl/epub/OEBPS/front-cover.html.ejs")); + +var _notes = _interopRequireDefault(__webpack_require__(/*! ./tpl/epub/OEBPS/notes.html */ "./src/tpl/epub/OEBPS/notes.html.ejs")); + +var _page = _interopRequireDefault(__webpack_require__(/*! ./tpl/epub/OEBPS/page.html */ "./src/tpl/epub/OEBPS/page.html.ejs")); + +var _tableOfContents = _interopRequireDefault(__webpack_require__(/*! ./tpl/epub/OEBPS/table-of-contents.html */ "./src/tpl/epub/OEBPS/table-of-contents.html.ejs")); + +var _titlePage = _interopRequireDefault(__webpack_require__(/*! ./tpl/epub/OEBPS/title-page.html */ "./src/tpl/epub/OEBPS/title-page.html.ejs")); + +var _book = _interopRequireDefault(__webpack_require__(/*! ./tpl/epub/book.opf */ "./src/tpl/epub/book.opf.ejs")); + +var _mimetype = _interopRequireDefault(__webpack_require__(/*! ./tpl/epub/mimetype */ "./src/tpl/epub/mimetype")); + +var _toc = _interopRequireDefault(__webpack_require__(/*! ./tpl/epub/toc.ncx */ "./src/tpl/epub/toc.ncx.ejs")); + +class jEpub { + constructor() { + this._I18n = {}; + this._Info = {}; + this._Uuid = {}; + this._Date = null; + this._Cover = null; + this._Pages = []; + this._Images = []; + this._Zip = {}; + } + + init(details) { + if (details instanceof JSZip) { + this._Zip = details; + return this; + } + + this._Info = Object.assign({}, { + i18n: 'en', + title: 'undefined', + author: 'undefined', + publisher: 'undefined', + description: '', + tags: [] + }, details); + this._Uuid = { + scheme: 'uuid', + id: utils.uuidv4() + }; + this._Date = utils.getISODate(); + if (!_i18n.default[this._Info.i18n]) throw "Unknown Language: ".concat(this._Info.i18n); + this._I18n = _i18n.default[this._Info.i18n]; + this._Zip = new JSZip(); + + this._Zip.file('mimetype', _mimetype.default); + + this._Zip.file('META-INF/container.xml', _container.default); + + this._Zip.file('OEBPS/title-page.html', ejs.render(_titlePage.default, { + i18n: this._I18n, + title: this._Info.title, + author: this._Info.author, + publisher: this._Info.publisher, + description: utils.parseDOM(this._Info.description), + tags: this._Info.tags + }, { + client: true + })); + + return this; + } + + static html2text(html, noBr = false) { + return utils.html2text(html, noBr); + } + + date(date) { + if (date instanceof Date) { + this._Date = utils.getISODate(date); + return this; + } else { + throw 'Date object is not valid'; + } + } + + uuid(id) { + if (utils.isEmpty(id)) { + throw 'UUID value is empty'; + } else { + let scheme = 'uuid'; + if (utils.validateUrl(id)) scheme = 'URI'; + this._Uuid = { + scheme: scheme, + id: id + }; + return this; + } + } + + cover(data) { + let ext, mime; + + if (data instanceof Blob) { + mime = data.type; + ext = utils.mime2ext(mime); + } else if (data instanceof ArrayBuffer) { + ext = (0, _imageType.default)(new Uint8Array(data)); + + if (ext) { + mime = ext.mime; + ext = utils.mime2ext(mime); + } + } else { + throw 'Cover data is not valid'; + } + + if (!ext) throw 'Cover data is not allowed'; + this._Cover = { + type: mime, + path: "OEBPS/cover-image.".concat(ext) + }; + + this._Zip.file(this._Cover.path, data); + + this._Zip.file('OEBPS/front-cover.html', ejs.render(_frontCover.default, { + i18n: this._I18n, + cover: this._Cover + }, { + client: true + })); + + return this; + } + + image(data, name) { + let ext, mime; + + if (data instanceof Blob) { + mime = data.type; + ext = utils.mime2ext(mime); + } else if (data instanceof ArrayBuffer) { + ext = (0, _imageType.default)(new Uint8Array(data)); + mime = ext.mime; + if (ext) ext = utils.mime2ext(mime); + } else { + throw 'Image data is not valid'; + } + + if (!ext) throw 'Image data is not allowed'; + const filePath = "assets/".concat(name, ".").concat(ext); + this._Images[name] = { + type: mime, + path: filePath + }; + + this._Zip.file("OEBPS/".concat(filePath), data); + + return this; + } + + notes(content) { + if (utils.isEmpty(content)) { + throw 'Notes is empty'; + } else { + this._Zip.file('OEBPS/notes.html', ejs.render(_notes.default, { + i18n: this._I18n, + notes: utils.parseDOM(content) + }, { + client: true + })); + + return this; + } + } + + add(title, content, index = this._Pages.length) { + if (utils.isEmpty(title)) { + throw 'Title is empty'; + } else if (utils.isEmpty(content)) { + throw "Content of ".concat(title, " is empty"); + } else { + if (!Array.isArray(content)) { + const template = ejs.compile(content, { + client: true + }); + content = template({ + image: this._Images + }, data => { + return ""); + }); + content = utils.parseDOM(content); + } + + this._Zip.file("OEBPS/page-".concat(index, ".html"), ejs.render(_page.default, { + i18n: this._I18n, + title: title, + content: content + }, { + client: true + })); + + this._Pages[index] = title; + return this; + } + } + + generate(type = 'blob', onUpdate) { + if (!JSZip.support[type]) throw "This browser does not support ".concat(type); + + let notes = this._Zip.file('OEBPS/notes.html'); + + notes = !notes ? false : true; + + this._Zip.file('book.opf', ejs.render(_book.default, { + i18n: this._I18n, + uuid: this._Uuid, + date: this._Date, + title: this._Info.title, + author: this._Info.author, + publisher: this._Info.publisher, + description: utils.html2text(this._Info.description, true), + tags: this._Info.tags, + cover: this._Cover, + pages: this._Pages, + notes: notes, + images: this._Images + }, { + client: true + })); + + this._Zip.file('OEBPS/table-of-contents.html', ejs.render(_tableOfContents.default, { + i18n: this._I18n, + pages: this._Pages + }, { + client: true + })); + + this._Zip.file('toc.ncx', ejs.render(_toc.default, { + i18n: this._I18n, + uuid: this._Uuid, + title: this._Info.title, + author: this._Info.author, + pages: this._Pages, + notes: notes + }, { + client: true + })); + + return this._Zip.generateAsync({ + type: type, + mimeType: _mimetype.default, + compression: 'DEFLATE', + compressionOptions: { + level: 9 + } + }, onUpdate); + } + +} + +exports["default"] = jEpub; +module.exports = exports["default"]; + +/***/ }), + +/***/ "./src/utils.js": +/*!**********************!*\ + !*** ./src/utils.js ***! + \**********************/ +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports.uuidv4 = uuidv4; +exports.isObject = isObject; +exports.isEmpty = isEmpty; +exports.getISODate = getISODate; +exports.parseDOM = parseDOM; +exports.html2text = html2text; +exports.validateUrl = validateUrl; +exports.mime2ext = mime2ext; + +/** + * Generates a UUID + * @see https://stackoverflow.com/a/2117523 + * @returns {string} uuid + */ +function uuidv4() { + return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)); +} +/** + * Checks if a value is object + * @see https://stackoverflow.com/a/14706877 + * @returns {boolean} + */ + + +function isObject(obj) { + const type = typeof obj; + return type === 'function' || type === 'object' && !!obj; +} +/** + * Checks if a value is empty + * @returns {boolean} + */ + + +function isEmpty(val) { + if (val === null) { + return true; + } else if (typeof val === 'string') { + return !val.trim(); + } + + return false; +} +/** + * Get current moment in ISO format + * @param {Object} date + * @returns {string} ISO date + */ + + +function getISODate(date = new Date()) { + return date.toISOString(); +} +/** + * Convert convert HTML to valid XHTML + * @param {String} html + * @param {String} outText return as plain text + */ + + +function parseDOM(html, outText = false) { + let doc = new DOMParser().parseFromString("
".concat(html), 'text/html'); + if (outText) return doc.body.textContent.trim(); + doc = new XMLSerializer().serializeToString(doc.body); + doc = doc.replace(/(^]*>|<\/body>$)/g, ''); + return doc; +} +/** + * Convert HTML to plain text + * @param {String} html + */ + + +function html2text(html, noBr = false) { + html = html.replace(/