Socket
Socket
Sign inDemoInstall

jepub

Package Overview
Dependencies
14
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.2.5 to 2.0.0

demo/lorem-ipsum.jpg

55

demo/script.js
/* eslint-disable no-console */
fetch('./cover-image.jpg').then(response => {
if (response.ok) return response.arrayBuffer();
throw 'Network response was not ok.';
}).then(buffer => {
(async () => {
const jepub = new jEpub({
const cover = await fetch('./cover-image.jpg').then(response => {
if (response.ok) return response.blob();
throw 'Network response was not ok.';
});
const jepub = new jEpub();
jepub.init({
title: 'Lorem Ipsum',

@@ -17,10 +20,16 @@ author: 'Cicero',

jepub.date(new Date(2013, 8, 15));
jepub.cover(cover).notes('<p class="no-indent">Dịch sang Tiếng Việt bởi <strong>Đỗ Việt</strong> - www.doviet.net</p>');
jepub.cover(buffer).notes('<p class="no-indent">Dịch sang Tiếng Việt bởi <strong>Đỗ Việt</strong> - www.doviet.net</p>');
let illustration = await fetch('./lorem-ipsum.jpg').then(response => {
if (response.ok) return response.blob();
throw 'Network response was not ok.';
});
jepub.image(illustration, 'lorem-ipsum');
jepub.add('Lorem Ipsum là gì?', [
'Lorem Ipsum chỉ đơn giản là một đoạn văn bản giả, được dùng vào việc trình bày và dàn trang phục vụ cho in ấn. Lorem Ipsum đã được sử dụng như một văn bản chuẩn cho ngành công nghiệp in ấn từ những năm 1500, khi một họa sĩ vô danh ghép nhiều đoạn văn bản với nhau để tạo thành một bản mẫu văn bản. Đoạn văn bản này không những đã tồn tại năm thế kỉ, mà khi được áp dụng vào tin học văn phòng, nội dung của nó vẫn không hề bị thay đổi. Nó đã được phổ biến trong những năm 1960 nhờ việc bán những bản giấy Letraset in những đoạn Lorem Ipsum, và gần đây hơn, được sử dụng trong các ứng dụng dàn trang, như Aldus PageMaker.',
'Trái với quan điểm chung của số đông, Lorem Ipsum không phải chỉ là một đoạn văn bản ngẫu nhiên. Người ta tìm thấy nguồn gốc của nó từ những tác phẩm văn học la-tinh cổ điển xuất hiện từ năm 45 trước Công Nguyên, nghĩa là nó đã có khoảng hơn 2000 tuổi. Một giáo sư của trường Hampden-Sydney College (bang Virginia - Mỹ) quan tâm tới một trong những từ la-tinh khó hiểu nhất, "consectetur", trích từ một đoạn của Lorem Ipsum, và đã nghiên cứu tất cả các ứng dụng của từ này trong văn học cổ điển, để từ đó tìm ra nguồn gốc không thể chối cãi của Lorem Ipsum. Thật ra, nó được tìm thấy trong các đoạn 1.10.32 và 1.10.33 của "De Finibus Bonorum et Malorum" (Đỉnh tối thượng của Cái Tốt và Cái Xấu) viết bởi Cicero vào năm 45 trước Công Nguyên. Cuốn sách này là một luận thuyết đạo lí rất phổ biến trong thời kì Phục Hưng. Dòng đầu tiên của Lorem Ipsum, "Lorem ipsum dolor sit amet..." được trích từ một câu trong đoạn thứ 1.10.32.',
'Trích đoạn chuẩn của Lorem Ipsum được sử dụng từ thế kỉ thứ 16 và được tái bản sau đó cho những người quan tâm đến nó. Đoạn 1.10.32 và 1.10.33 trong cuốn "De Finibus Bonorum et Malorum" của Cicero cũng được tái bản lại theo đúng cấu trúc gốc, kèm theo phiên bản tiếng Anh được dịch bởi H. Rackham vào năm 1914.'
]);
jepub.add('Lorem Ipsum là gì?', `
<p class="indent">Lorem Ipsum chỉ đơn giản là một đoạn văn bản giả, được dùng vào việc trình bày và dàn trang phục vụ cho in ấn. Lorem Ipsum đã được sử dụng như một văn bản chuẩn cho ngành công nghiệp in ấn từ những năm 1500, khi một họa sĩ vô danh ghép nhiều đoạn văn bản với nhau để tạo thành một bản mẫu văn bản. Đoạn văn bản này không những đã tồn tại năm thế kỉ, mà khi được áp dụng vào tin học văn phòng, nội dung của nó vẫn không hề bị thay đổi. Nó đã được phổ biến trong những năm 1960 nhờ việc bán những bản giấy Letraset in những đoạn Lorem Ipsum, và gần đây hơn, được sử dụng trong các ứng dụng dàn trang, như Aldus PageMaker.</p>
<p style="text-align:center;"><%= image['lorem-ipsum'] %></p>
<p class="indent">Trái với quan điểm chung của số đông, Lorem Ipsum không phải chỉ là một đoạn văn bản ngẫu nhiên. Người ta tìm thấy nguồn gốc của nó từ những tác phẩm văn học la-tinh cổ điển xuất hiện từ năm 45 trước Công Nguyên, nghĩa là nó đã có khoảng hơn 2000 tuổi. Một giáo sư của trường Hampden-Sydney College (bang Virginia - Mỹ) quan tâm tới một trong những từ la-tinh khó hiểu nhất, "consectetur", trích từ một đoạn của Lorem Ipsum, và đã nghiên cứu tất cả các ứng dụng của từ này trong văn học cổ điển, để từ đó tìm ra nguồn gốc không thể chối cãi của Lorem Ipsum. Thật ra, nó được tìm thấy trong các đoạn 1.10.32 và 1.10.33 của "De Finibus Bonorum et Malorum" (Đỉnh tối thượng của Cái Tốt và Cái Xấu) viết bởi Cicero vào năm 45 trước Công Nguyên. Cuốn sách này là một luận thuyết đạo lí rất phổ biến trong thời kì Phục Hưng. Dòng đầu tiên của Lorem Ipsum, "Lorem ipsum dolor sit amet..." được trích từ một câu trong đoạn thứ 1.10.32.</p>
<p class="indent">Trích đoạn chuẩn của Lorem Ipsum được sử dụng từ thế kỉ thứ 16 và được tái bản sau đó cho những người quan tâm đến nó. Đoạn 1.10.32 và 1.10.33 trong cuốn "De Finibus Bonorum et Malorum" của Cicero cũng được tái bản lại theo đúng cấu trúc gốc, kèm theo phiên bản tiếng Anh được dịch bởi H. Rackham vào năm 1914.</p>
`);

@@ -34,19 +43,13 @@ jepub.add('Tại sao lại sử dụng nó?', '<p class="indent">Chúng ta vẫn biết rằng, làm việc với một đoạn văn bản dễ đọc và rõ nghĩa dễ gây rối trí và cản trở việc tập trung vào yếu tố trình bày văn bản. Lorem Ipsum có ưu điểm hơn so với đoạn văn bản chỉ gồm nội dung kiểu "Nội dung, nội dung, nội dung" là nó khiến văn bản giống thật hơn, bình thường hơn. Nhiều phần mềm thiết kế giao diện web và dàn trang ngày nay đã sử dụng Lorem Ipsum làm đoạn văn bản giả, và nếu bạn thử tìm các đoạn "Lorem ipsum" trên mạng thì sẽ khám phá ra nhiều trang web hiện vẫn đang trong quá trình xây dựng. Có nhiều phiên bản khác nhau đã xuất hiện, đôi khi do vô tình, nhiều khi do cố ý (xen thêm vào những câu hài hước hay thông tục).</p>');

console.log(jepub);
const blob = await jepub.generate();
console.log(blob);
jepub.generate().then(content => {
console.log(content);
let url = URL.createObjectURL(blob);
let link = document.createElement('a');
let url = URL.createObjectURL(content);
document.body.appendChild(link);
link.href = url;
link.textContent = 'Download EPUB';
link.download = 'lorem-ipsum.epub';
let link = document.createElement('a');
document.body.appendChild(link);
link.href = url;
link.textContent = 'Download EPUB';
link.download = 'lorem-ipsum.epub';
}).catch(err => {
console.error(err);
});
}).catch(err => {
console.error(err);
});
})();
{
"name": "jepub",
"version": "1.2.5",
"version": "2.0.0",
"description": "Generate simple EPUB books with JavaScript.",

@@ -5,0 +5,0 @@ "main": "src/jepub.js",

@@ -28,6 +28,22 @@ # jEpub

## Dependencies
jEpub requires [JSZip](https://github.com/Stuk/jszip) and [EJS](https://github.com/mde/ejs). Make sure these libraries are loaded before starting your code.
```html
<script src="jszip.js"></script>
<script src="ejs.js"></script>
<script src="jepub.js"></script>
<script>
const jepub = new jEpub()
// jepub.init({
// do something
</script>
```
## Usage
```typescript
const jepub = new jEpub({
const jepub = new jEpub()
jepub.init({
i18n: 'en', // Internationalization

@@ -39,7 +55,8 @@ title: 'Book title',

tags: [ 'epub', 'tag' ] // optional
});
})
```
- **i18n** only include the language codes defined in [`i18n.json`](https://github.com/lelinhtinh/jEpub/raw/master/src/i18n.json)
- **i18n** only include the language codes defined in [`i18n.json`](https://github.com/lelinhtinh/jEpub/blob/master/src/i18n.json)
- **description**: HTML string.
- **tags**: Array.

@@ -60,3 +77,3 @@ ### Set published date

- **id** is unique.
- **id**: Unique id.

@@ -66,6 +83,6 @@ ### Add cover

```typescript
jepub.cover(buffer: object)
jepub.cover(blob: object)
```
- **buffer**: ArrayBuffer Object from XMLHttpRequest.
- **blob**: Blob Object from XMLHttpRequest.

@@ -91,10 +108,19 @@ ### Add notes

### Add image
```typescript
jepub.image(blob: object, IMG_ID: string)
```
- **blob**: Blob Object from XMLHttpRequest.
- **IMG_ID**: Unique id.
Place `<%= image[IMG_ID] %>` inside the chapter's content *(HTML string only)*, where you want to display it.
### Generate EPUB `*`
```typescript
jepub.generate(type = 'blob')
jepub.generate()
```
- **type**: Possible values `blob` (*default*), `base64`, `binarystring`, `array`, `uint8array`, `arraybuffer`, `nodebuffer` (*NodeJS*).
### Static methods `+`

@@ -123,22 +149,4 @@

### VSCode
Fix [**Markdown All in One `#41`**](https://github.com/neilsustc/vscode-markdown/issues/41): Add to `keybindings.json`
```json
{
"key": "backspace",
"command": "-markdown.extension.onBackspaceKey"
},
{
"key": "alt+backspace",
"command": "markdown.extension.onBackspaceKey",
"when": "editorTextFocus && !editorReadonly && !suggestWidgetVisible && editorLangId == 'markdown'"
}
```
Start **Chrome** with the `--remote-debugging-port=9222` flag when debugging in the [`attach`](https://github.com/Microsoft/vscode-chrome-debug#attach) mode.
## License
ISC. Copyright 2018 [lelinhtinh](https://github.com/lelinhtinh)
'use strict';
import JSZip from 'jszip';
import ejs from 'ejs';
import * as utils from './utils';

@@ -22,3 +19,18 @@

export default class jEpub {
constructor(details) {
constructor() {
this._I18n = {};
this._Info = {};
this._Uuid = {};
this._Date = null;
this._Cover = null;
this._Pages = [];
this._Images = [];
this._Zip = {};
}
init(details) {
if (!JSZip.support.blob) throw 'This browser does not support Blob';
this._Info = Object.assign({}, {

@@ -32,3 +44,2 @@ i18n: 'vi',

}, details);
this._Uuid = {

@@ -39,6 +50,20 @@ scheme: 'uuid',

this._Date = utils.getISODate();
this._Cover = '';
this._Notes = '';
this._Pages = [];
if (!language[this._Info.i18n]) throw `Unknown Language: ${this._Info.i18n}`;
this._I18n = language[this._Info.i18n];
this._Zip = new JSZip();
this._Zip.file('mimetype', mime);
this._Zip.file('META-INF/container.xml', container);
this._Zip.file('OEBPS/jackson.css', style);
this._Zip.file('OEBPS/title-page.html', ejs.render(info, {
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
}));
}

@@ -75,4 +100,16 @@

cover(data) {
if (data instanceof ArrayBuffer) {
this._Cover = data;
if (data instanceof Blob) {
const ext = utils.mime2ext(data.type);
if (!ext) throw 'Image data is not allowed';
this._Cover = {
type: data.type,
path: `OEBPS/cover-image.${ext}`
};
this._Zip.file(this._Cover.path, data);
this._Zip.file('OEBPS/front-cover.html', ejs.render(cover, {
i18n: this._I18n,
cover: this._Cover
}, {
client: true
}));
return this;

@@ -84,2 +121,18 @@ } else {

image(data, name) {
if (data instanceof Blob) {
const ext = utils.mime2ext(data.type);
if (!ext) throw 'Image data is not allowed';
const filePath = `assets/${name}.${ext}`;
this._Images[name] = {
type: data.type,
path: filePath
};
this._Zip.file(`OEBPS/${filePath}`, data);
return this;
} else {
throw 'Image data is not valid';
}
}
notes(content) {

@@ -89,3 +142,8 @@ if (utils.isEmpty(content)) {

} else {
this._Notes = content;
this._Zip.file('OEBPS/notes.html', ejs.render(notes, {
i18n: this._I18n,
notes: utils.parseDOM(content)
}, {
client: true
}));
return this;

@@ -101,6 +159,21 @@ }

} else {
this._Pages.push({
if (!Array.isArray(content)) {
const template = ejs.compile(content, {
client: true
});
content = template({
image: this._Images
}, data => {
return `<img src="${(data ? data.path: 'data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=')}" alt=""></img>`;
});
content = utils.parseDOM(content);
}
this._Zip.file(`OEBPS/page-${this._Pages.length}.html`, ejs.render(page, {
i18n: this._I18n,
title: title,
content: content
});
}, {
client: true
}));
this._Pages.push(title);
return this;

@@ -110,17 +183,8 @@ }

generate(type = 'blob') {
const zip = new JSZip();
generate() {
let notes = this._Zip.file('OEBPS/notes.html');
notes = !notes ? false : true;
if (!JSZip.support[type]) throw `This browser does not support ${type}`;
if (!language[this._Info.i18n]) throw `Unknown Language: ${this._Info.i18n}`;
const i18n = language[this._Info.i18n];
zip.file('mimetype', mime);
zip.file('META-INF/container.xml', container);
let oebps = zip.folder('OEBPS');
zip.file('book.opf', ejs.render(bookConfig, {
i18n: i18n,
this._Zip.file('book.opf', ejs.render(bookConfig, {
i18n: this._I18n,
uuid: this._Uuid,

@@ -135,48 +199,17 @@ date: this._Date,

pages: this._Pages,
notes: this._Notes
notes: notes,
images: this._Images
}, {
client: true
}));
if (this._Cover) {
oebps.file('cover-image.jpg', this._Cover);
oebps.file('front-cover.html', ejs.render(cover, {
i18n: i18n
}));
}
oebps.file('title-page.html', ejs.render(info, {
i18n: i18n,
title: this._Info.title,
author: this._Info.author,
publisher: this._Info.publisher,
description: utils.parseDOM(this._Info.description),
tags: this._Info.tags,
}));
oebps.file('table-of-contents.html', ejs.render(tocInBook, {
i18n: i18n,
this._Zip.file('OEBPS/table-of-contents.html', ejs.render(tocInBook, {
i18n: this._I18n,
pages: this._Pages
}, {
client: true
}));
this._Pages.forEach((item, index) => {
let content = item.content;
if (!Array.isArray(content)) content = utils.parseDOM(content);
oebps.file(`page-${index}.html`, ejs.render(page, {
i18n: i18n,
title: item.title,
content: content
}));
});
if (this._Notes) {
oebps.file('notes.html', ejs.render(notes, {
i18n: i18n,
notes: utils.parseDOM(this._Notes)
}));
}
oebps.file('jackson.css', style);
zip.file('toc.ncx', ejs.render(toc, {
i18n: i18n,
this._Zip.file('toc.ncx', ejs.render(toc, {
i18n: this._I18n,
uuid: this._Uuid,

@@ -186,7 +219,9 @@ title: this._Info.title,

pages: this._Pages,
notes: this._Notes
notes: notes
}, {
client: true
}));
return zip.generateAsync({
type: type,
return this._Zip.generateAsync({
type: 'blob',
mimeType: mime,

@@ -193,0 +228,0 @@ compression: 'DEFLATE',

@@ -8,3 +8,3 @@ /**

export function uuidv4() {
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)

@@ -77,1 +77,27 @@ );

}
/**
* Convert MIME type to extension
* @param {String} mime
*/
export function mime2ext(mime) {
let ext = null;
switch (mime) {
case 'image/gif':
ext = 'gif';
break;
case 'image/jpeg':
ext = 'jpg';
break;
case 'image/png':
ext = 'png';
break;
case 'image/svg+xml':
ext = 'svg';
break;
default:
ext = null;
break;
}
return ext;
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc