@papyrus-sdk/engine-epub 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,53 @@
1
+ import { BaseDocumentEngine } from '@papyrus-sdk/core';
2
+ import { DocumentLoadInput, TextSelection, TextItem, OutlineItem } from '@papyrus-sdk/types';
3
+
4
+ declare class EPUBEngine extends BaseDocumentEngine {
5
+ private book;
6
+ private spineItems;
7
+ private renditions;
8
+ private renditionTargets;
9
+ private pageSizes;
10
+ private currentPage;
11
+ private zoom;
12
+ private rotation;
13
+ getRenderTargetType(): 'element';
14
+ load(input: DocumentLoadInput): Promise<void>;
15
+ getPageCount(): number;
16
+ getCurrentPage(): number;
17
+ goToPage(page: number): void;
18
+ setZoom(zoom: number): void;
19
+ getZoom(): number;
20
+ rotate(direction: 'clockwise' | 'counterclockwise'): void;
21
+ getRotation(): number;
22
+ getPageDimensions(pageIndex: number): Promise<{
23
+ width: number;
24
+ height: number;
25
+ }>;
26
+ selectText(pageIndex: number, rect: {
27
+ x: number;
28
+ y: number;
29
+ width: number;
30
+ height: number;
31
+ }): Promise<TextSelection | null>;
32
+ renderPage(pageIndex: number, target: any, scale: number): Promise<void>;
33
+ renderTextLayer(pageIndex: number, container: any, scale: number): Promise<void>;
34
+ getTextContent(pageIndex: number): Promise<TextItem[]>;
35
+ getOutline(): Promise<OutlineItem[]>;
36
+ getPageIndex(dest: any): Promise<number | null>;
37
+ destroy(): void;
38
+ private applyRenditionTheme;
39
+ private getSpineIndexByHref;
40
+ private normalizeHref;
41
+ private isUriSource;
42
+ private isDataSource;
43
+ private isFileLike;
44
+ private normalizeLoadInput;
45
+ private isLoadRequest;
46
+ private resolveSource;
47
+ private parseDataUri;
48
+ private decodeBase64;
49
+ private looksLikeUri;
50
+ private isLikelyBase64;
51
+ }
52
+
53
+ export { EPUBEngine };
@@ -0,0 +1,53 @@
1
+ import { BaseDocumentEngine } from '@papyrus-sdk/core';
2
+ import { DocumentLoadInput, TextSelection, TextItem, OutlineItem } from '@papyrus-sdk/types';
3
+
4
+ declare class EPUBEngine extends BaseDocumentEngine {
5
+ private book;
6
+ private spineItems;
7
+ private renditions;
8
+ private renditionTargets;
9
+ private pageSizes;
10
+ private currentPage;
11
+ private zoom;
12
+ private rotation;
13
+ getRenderTargetType(): 'element';
14
+ load(input: DocumentLoadInput): Promise<void>;
15
+ getPageCount(): number;
16
+ getCurrentPage(): number;
17
+ goToPage(page: number): void;
18
+ setZoom(zoom: number): void;
19
+ getZoom(): number;
20
+ rotate(direction: 'clockwise' | 'counterclockwise'): void;
21
+ getRotation(): number;
22
+ getPageDimensions(pageIndex: number): Promise<{
23
+ width: number;
24
+ height: number;
25
+ }>;
26
+ selectText(pageIndex: number, rect: {
27
+ x: number;
28
+ y: number;
29
+ width: number;
30
+ height: number;
31
+ }): Promise<TextSelection | null>;
32
+ renderPage(pageIndex: number, target: any, scale: number): Promise<void>;
33
+ renderTextLayer(pageIndex: number, container: any, scale: number): Promise<void>;
34
+ getTextContent(pageIndex: number): Promise<TextItem[]>;
35
+ getOutline(): Promise<OutlineItem[]>;
36
+ getPageIndex(dest: any): Promise<number | null>;
37
+ destroy(): void;
38
+ private applyRenditionTheme;
39
+ private getSpineIndexByHref;
40
+ private normalizeHref;
41
+ private isUriSource;
42
+ private isDataSource;
43
+ private isFileLike;
44
+ private normalizeLoadInput;
45
+ private isLoadRequest;
46
+ private resolveSource;
47
+ private parseDataUri;
48
+ private decodeBase64;
49
+ private looksLikeUri;
50
+ private isLikelyBase64;
51
+ }
52
+
53
+ export { EPUBEngine };
package/dist/index.js ADDED
@@ -0,0 +1,294 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // index.ts
30
+ var index_exports = {};
31
+ __export(index_exports, {
32
+ EPUBEngine: () => EPUBEngine
33
+ });
34
+ module.exports = __toCommonJS(index_exports);
35
+ var import_epubjs = __toESM(require("epubjs"));
36
+ var import_core = require("@papyrus-sdk/core");
37
+ var EPUBEngine = class extends import_core.BaseDocumentEngine {
38
+ constructor() {
39
+ super(...arguments);
40
+ this.book = null;
41
+ this.spineItems = [];
42
+ this.renditions = /* @__PURE__ */ new Map();
43
+ this.renditionTargets = /* @__PURE__ */ new Map();
44
+ this.pageSizes = /* @__PURE__ */ new Map();
45
+ this.currentPage = 1;
46
+ this.zoom = 1;
47
+ this.rotation = 0;
48
+ }
49
+ getRenderTargetType() {
50
+ return "element";
51
+ }
52
+ async load(input) {
53
+ try {
54
+ const { source, type } = this.normalizeLoadInput(input);
55
+ if (type && type !== "epub") {
56
+ throw new Error(`[EPUBEngine] Tipo de documento n\xE3o suportado: ${type}`);
57
+ }
58
+ const data = await this.resolveSource(source);
59
+ this.book = (0, import_epubjs.default)(data);
60
+ await this.book.ready;
61
+ this.spineItems = this.book.spine?.items ?? [];
62
+ this.currentPage = 1;
63
+ this.renditions.forEach((rendition) => rendition?.destroy?.());
64
+ this.renditions.clear();
65
+ this.renditionTargets.clear();
66
+ this.pageSizes.clear();
67
+ } catch (error) {
68
+ console.error("[EPUBEngine] Erro ao carregar:", error);
69
+ throw error;
70
+ }
71
+ }
72
+ getPageCount() {
73
+ return this.spineItems.length;
74
+ }
75
+ getCurrentPage() {
76
+ return this.currentPage;
77
+ }
78
+ goToPage(page) {
79
+ if (page >= 1 && page <= this.getPageCount()) this.currentPage = page;
80
+ }
81
+ setZoom(zoom) {
82
+ this.zoom = Math.max(0.5, Math.min(3, zoom));
83
+ this.renditions.forEach((rendition) => this.applyRenditionTheme(rendition));
84
+ }
85
+ getZoom() {
86
+ return this.zoom;
87
+ }
88
+ rotate(direction) {
89
+ if (direction === "clockwise") this.rotation = (this.rotation + 90) % 360;
90
+ else {
91
+ this.rotation = (this.rotation - 90) % 360;
92
+ if (this.rotation < 0) this.rotation += 360;
93
+ }
94
+ }
95
+ getRotation() {
96
+ return this.rotation;
97
+ }
98
+ async getPageDimensions(pageIndex) {
99
+ const size = this.pageSizes.get(pageIndex);
100
+ if (size) return size;
101
+ return { width: 0, height: 0 };
102
+ }
103
+ async selectText(pageIndex, rect) {
104
+ void pageIndex;
105
+ void rect;
106
+ return null;
107
+ }
108
+ async renderPage(pageIndex, target, scale) {
109
+ const scaleKey = Math.round(scale * 1e3);
110
+ const element = target;
111
+ if (!this.book || !element) return;
112
+ const spineItem = this.spineItems[pageIndex];
113
+ if (!spineItem) return;
114
+ const width = element.clientWidth > 0 ? element.clientWidth : 640;
115
+ const height = element.clientHeight > 0 ? element.clientHeight : 900;
116
+ element.style.width = `${width}px`;
117
+ element.style.height = `${height}px`;
118
+ if (width >= 320 && height >= 480) this.pageSizes.set(pageIndex, { width, height });
119
+ const renditionKey = `${pageIndex}:${scaleKey}`;
120
+ let rendition = this.renditions.get(renditionKey);
121
+ const currentTarget = this.renditionTargets.get(renditionKey);
122
+ if (!rendition || currentTarget !== element) {
123
+ if (rendition?.destroy) rendition.destroy();
124
+ element.innerHTML = "";
125
+ rendition = this.book.renderTo(element, {
126
+ width,
127
+ height,
128
+ flow: "paginated",
129
+ spread: "none"
130
+ });
131
+ this.renditions.set(renditionKey, rendition);
132
+ this.renditionTargets.set(renditionKey, element);
133
+ if (rendition?.hooks?.content?.register) {
134
+ rendition.hooks.content.register((contents) => {
135
+ const frame = contents?.document?.defaultView?.frameElement;
136
+ if (frame) {
137
+ frame.setAttribute("sandbox", "allow-scripts allow-same-origin");
138
+ }
139
+ });
140
+ }
141
+ } else if (typeof rendition.resize === "function") {
142
+ rendition.resize(width, height);
143
+ }
144
+ if (rendition) {
145
+ this.applyRenditionTheme(rendition);
146
+ const targetRef = spineItem.href || spineItem.idref || spineItem.cfiBase || pageIndex;
147
+ await rendition.display(targetRef);
148
+ }
149
+ }
150
+ async renderTextLayer(pageIndex, container, scale) {
151
+ void pageIndex;
152
+ void scale;
153
+ const element = container;
154
+ if (element) element.innerHTML = "";
155
+ }
156
+ async getTextContent(pageIndex) {
157
+ if (!this.book) return [];
158
+ const spineItem = this.spineItems[pageIndex];
159
+ if (!spineItem) return [];
160
+ try {
161
+ const section = this.book.spine.get(spineItem.idref || spineItem.href);
162
+ const text = typeof section?.text === "function" ? await section.text() : "";
163
+ if (!text) return [];
164
+ return [{
165
+ str: text,
166
+ dir: "ltr",
167
+ width: 0,
168
+ height: 0,
169
+ transform: [1, 0, 0, 1, 0, 0],
170
+ fontName: "default"
171
+ }];
172
+ } catch {
173
+ return [];
174
+ }
175
+ }
176
+ async getOutline() {
177
+ if (!this.book) return [];
178
+ const nav = await this.book.loaded?.navigation;
179
+ const toc = nav?.toc ?? [];
180
+ if (!toc.length) return [];
181
+ const mapItem = (item) => {
182
+ const title = item.label || item.title || "";
183
+ const pageIndex = this.getSpineIndexByHref(item.href || "");
184
+ const children = Array.isArray(item.subitems) ? item.subitems.map(mapItem) : [];
185
+ const outlineItem = { title, pageIndex };
186
+ if (children.length > 0) outlineItem.children = children;
187
+ return outlineItem;
188
+ };
189
+ return toc.map(mapItem);
190
+ }
191
+ async getPageIndex(dest) {
192
+ if (!dest) return null;
193
+ if (typeof dest === "string") return this.getSpineIndexByHref(dest);
194
+ return null;
195
+ }
196
+ destroy() {
197
+ this.renditions.forEach((rendition) => rendition?.destroy?.());
198
+ this.renditions.clear();
199
+ this.renditionTargets.clear();
200
+ this.pageSizes.clear();
201
+ if (this.book?.destroy) this.book.destroy();
202
+ this.book = null;
203
+ this.spineItems = [];
204
+ }
205
+ applyRenditionTheme(rendition) {
206
+ if (!rendition) return;
207
+ const fontSize = `${Math.round(this.zoom * 100)}%`;
208
+ if (rendition.themes?.fontSize) {
209
+ rendition.themes.fontSize(fontSize);
210
+ } else if (rendition.themes?.override) {
211
+ rendition.themes.override("font-size", fontSize);
212
+ }
213
+ }
214
+ getSpineIndexByHref(href) {
215
+ const normalized = this.normalizeHref(href);
216
+ if (!normalized) return -1;
217
+ const index = this.spineItems.findIndex((item) => this.normalizeHref(item.href) === normalized);
218
+ return index;
219
+ }
220
+ normalizeHref(href) {
221
+ return href.split("#")[0];
222
+ }
223
+ isUriSource(source) {
224
+ return typeof source === "object" && source !== null && "uri" in source;
225
+ }
226
+ isDataSource(source) {
227
+ return typeof source === "object" && source !== null && "data" in source;
228
+ }
229
+ isFileLike(source) {
230
+ return typeof source === "object" && source !== null && typeof source.arrayBuffer === "function";
231
+ }
232
+ normalizeLoadInput(input) {
233
+ if (this.isLoadRequest(input)) {
234
+ return { source: input.source, type: input.type };
235
+ }
236
+ return { source: input };
237
+ }
238
+ isLoadRequest(input) {
239
+ return typeof input === "object" && input !== null && "source" in input && "type" in input;
240
+ }
241
+ async resolveSource(source) {
242
+ if (typeof source === "string") {
243
+ const dataUri = this.parseDataUri(source);
244
+ if (dataUri) {
245
+ return dataUri.isBase64 ? this.decodeBase64(dataUri.data) : dataUri.data;
246
+ }
247
+ if (this.looksLikeUri(source)) {
248
+ return source;
249
+ }
250
+ if (this.isLikelyBase64(source)) {
251
+ return this.decodeBase64(source);
252
+ }
253
+ return source;
254
+ }
255
+ if (this.isUriSource(source)) return source.uri;
256
+ if (this.isDataSource(source)) return source.data;
257
+ if (this.isFileLike(source)) return await source.arrayBuffer();
258
+ return source;
259
+ }
260
+ parseDataUri(value) {
261
+ const match = /^data:([^;,]+)?(;base64)?,(.*)$/.exec(value);
262
+ if (!match) return null;
263
+ const isBase64 = Boolean(match[2]);
264
+ const data = match[3] ?? "";
265
+ return { isBase64, data };
266
+ }
267
+ decodeBase64(value) {
268
+ const clean = value.replace(/\s/g, "");
269
+ if (typeof atob !== "function") {
270
+ throw new Error("[EPUBEngine] atob n\xE3o est\xE1 dispon\xEDvel para decodificar base64.");
271
+ }
272
+ const binary = atob(clean);
273
+ const len = binary.length;
274
+ const bytes = new Uint8Array(len);
275
+ for (let i = 0; i < len; i += 1) {
276
+ bytes[i] = binary.charCodeAt(i);
277
+ }
278
+ return bytes;
279
+ }
280
+ looksLikeUri(value) {
281
+ return value.startsWith("http://") || value.startsWith("https://") || value.startsWith("/") || value.startsWith("./") || value.startsWith("../") || value.startsWith("file://");
282
+ }
283
+ isLikelyBase64(value) {
284
+ if (this.looksLikeUri(value)) return false;
285
+ if (value.includes(".")) return false;
286
+ if (value.length < 16) return false;
287
+ return /^[A-Za-z0-9+/=]+$/.test(value);
288
+ }
289
+ };
290
+ // Annotate the CommonJS export names for ESM import in node:
291
+ 0 && (module.exports = {
292
+ EPUBEngine
293
+ });
294
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../index.ts"],"sourcesContent":["import ePub from 'epubjs';\r\nimport { BaseDocumentEngine } from '@papyrus-sdk/core';\nimport { DocumentLoadInput, DocumentLoadRequest, DocumentSource, DocumentType, TextItem, OutlineItem, FileLike, TextSelection } from '@papyrus-sdk/types';\n\r\nexport class EPUBEngine extends BaseDocumentEngine {\r\n private book: any = null;\r\n private spineItems: any[] = [];\r\n private renditions = new Map<string, any>();\r\n private renditionTargets = new Map<string, HTMLElement>();\r\n private pageSizes = new Map<number, { width: number; height: number }>();\r\n private currentPage: number = 1;\r\n private zoom: number = 1.0;\r\n private rotation: number = 0;\r\n\r\n getRenderTargetType(): 'element' { return 'element'; }\r\n\r\n async load(input: DocumentLoadInput): Promise<void> {\n try {\n const { source, type } = this.normalizeLoadInput(input);\n if (type && type !== 'epub') {\n throw new Error(`[EPUBEngine] Tipo de documento não suportado: ${type}`);\n }\n\n const data = await this.resolveSource(source);\n\n this.book = ePub(data);\n await this.book.ready;\n this.spineItems = this.book.spine?.items ?? [];\r\n this.currentPage = 1;\r\n this.renditions.forEach((rendition) => rendition?.destroy?.());\r\n this.renditions.clear();\r\n this.renditionTargets.clear();\r\n this.pageSizes.clear();\r\n } catch (error) {\r\n console.error('[EPUBEngine] Erro ao carregar:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n getPageCount(): number { return this.spineItems.length; }\r\n getCurrentPage(): number { return this.currentPage; }\r\n goToPage(page: number): void {\r\n if (page >= 1 && page <= this.getPageCount()) this.currentPage = page;\r\n }\r\n setZoom(zoom: number): void {\r\n this.zoom = Math.max(0.5, Math.min(3.0, zoom));\r\n this.renditions.forEach((rendition) => this.applyRenditionTheme(rendition));\r\n }\r\n getZoom(): number { return this.zoom; }\r\n\r\n rotate(direction: 'clockwise' | 'counterclockwise'): void {\r\n if (direction === 'clockwise') this.rotation = (this.rotation + 90) % 360;\r\n else { this.rotation = (this.rotation - 90) % 360; if (this.rotation < 0) this.rotation += 360; }\r\n }\r\n\r\n getRotation(): number { return this.rotation; }\r\n\r\n async getPageDimensions(pageIndex: number): Promise<{ width: number; height: number }> {\r\n const size = this.pageSizes.get(pageIndex);\r\n if (size) return size;\r\n return { width: 0, height: 0 };\r\n }\r\n\r\n async selectText(\r\n pageIndex: number,\r\n rect: { x: number; y: number; width: number; height: number }\r\n ): Promise<TextSelection | null> {\r\n void pageIndex;\r\n void rect;\r\n return null;\r\n }\r\n\r\n async renderPage(pageIndex: number, target: any, scale: number): Promise<void> {\r\n const scaleKey = Math.round(scale * 1000);\r\n const element = target as HTMLElement;\r\n if (!this.book || !element) return;\r\n\r\n const spineItem = this.spineItems[pageIndex];\r\n if (!spineItem) return;\r\n\r\n const width = element.clientWidth > 0 ? element.clientWidth : 640;\r\n const height = element.clientHeight > 0 ? element.clientHeight : 900;\r\n element.style.width = `${width}px`;\r\n element.style.height = `${height}px`;\r\n if (width >= 320 && height >= 480) this.pageSizes.set(pageIndex, { width, height });\r\n\r\n const renditionKey = `${pageIndex}:${scaleKey}`;\r\n let rendition = this.renditions.get(renditionKey);\r\n const currentTarget = this.renditionTargets.get(renditionKey);\r\n if (!rendition || currentTarget !== element) {\r\n if (rendition?.destroy) rendition.destroy();\r\n element.innerHTML = '';\r\n rendition = this.book.renderTo(element, {\r\n width,\r\n height,\r\n flow: 'paginated',\r\n spread: 'none',\r\n });\r\n this.renditions.set(renditionKey, rendition);\r\n this.renditionTargets.set(renditionKey, element);\r\n if (rendition?.hooks?.content?.register) {\r\n rendition.hooks.content.register((contents: any) => {\r\n const frame = contents?.document?.defaultView?.frameElement as HTMLIFrameElement | null;\r\n if (frame) {\r\n frame.setAttribute('sandbox', 'allow-scripts allow-same-origin');\r\n }\r\n });\r\n }\r\n } else if (typeof rendition.resize === 'function') {\r\n rendition.resize(width, height);\r\n }\r\n\r\n if (rendition) {\r\n this.applyRenditionTheme(rendition);\r\n const targetRef = spineItem.href || spineItem.idref || spineItem.cfiBase || pageIndex;\r\n await rendition.display(targetRef);\r\n }\r\n }\r\n\r\n async renderTextLayer(pageIndex: number, container: any, scale: number): Promise<void> {\r\n void pageIndex;\r\n void scale;\r\n const element = container as HTMLElement;\r\n if (element) element.innerHTML = '';\r\n }\r\n\r\n async getTextContent(pageIndex: number): Promise<TextItem[]> {\r\n if (!this.book) return [];\r\n const spineItem = this.spineItems[pageIndex];\r\n if (!spineItem) return [];\r\n\r\n try {\r\n const section = this.book.spine.get(spineItem.idref || spineItem.href);\r\n const text = typeof section?.text === 'function' ? await section.text() : '';\r\n if (!text) return [];\r\n return [{\r\n str: text,\r\n dir: 'ltr',\r\n width: 0,\r\n height: 0,\r\n transform: [1, 0, 0, 1, 0, 0],\r\n fontName: 'default',\r\n }];\r\n } catch {\r\n return [];\r\n }\r\n }\r\n\r\n async getOutline(): Promise<OutlineItem[]> {\r\n if (!this.book) return [];\r\n const nav = await this.book.loaded?.navigation;\r\n const toc = nav?.toc ?? [];\r\n if (!toc.length) return [];\r\n\r\n const mapItem = (item: any): OutlineItem => {\r\n const title = item.label || item.title || '';\r\n const pageIndex = this.getSpineIndexByHref(item.href || '');\r\n const children = Array.isArray(item.subitems) ? item.subitems.map(mapItem) : [];\r\n const outlineItem: OutlineItem = { title, pageIndex };\r\n if (children.length > 0) outlineItem.children = children;\r\n return outlineItem;\r\n };\r\n\r\n return toc.map(mapItem);\r\n }\r\n\r\n async getPageIndex(dest: any): Promise<number | null> {\r\n if (!dest) return null;\r\n if (typeof dest === 'string') return this.getSpineIndexByHref(dest);\r\n return null;\r\n }\r\n\r\n destroy(): void {\r\n this.renditions.forEach((rendition) => rendition?.destroy?.());\r\n this.renditions.clear();\r\n this.renditionTargets.clear();\r\n this.pageSizes.clear();\r\n if (this.book?.destroy) this.book.destroy();\r\n this.book = null;\r\n this.spineItems = [];\r\n }\r\n\r\n private applyRenditionTheme(rendition: any): void {\r\n if (!rendition) return;\r\n const fontSize = `${Math.round(this.zoom * 100)}%`;\r\n if (rendition.themes?.fontSize) {\r\n rendition.themes.fontSize(fontSize);\r\n } else if (rendition.themes?.override) {\r\n rendition.themes.override('font-size', fontSize);\r\n }\r\n }\r\n\r\n private getSpineIndexByHref(href: string): number {\r\n const normalized = this.normalizeHref(href);\r\n if (!normalized) return -1;\r\n const index = this.spineItems.findIndex((item) => this.normalizeHref(item.href) === normalized);\r\n return index;\r\n }\r\n\r\n private normalizeHref(href: string): string {\r\n return href.split('#')[0];\r\n }\r\n\r\n private isUriSource(source: DocumentSource): source is { uri: string } {\r\n return typeof source === 'object' && source !== null && 'uri' in source;\r\n }\r\n\r\n private isDataSource(source: DocumentSource): source is { data: ArrayBuffer | Uint8Array } {\r\n return typeof source === 'object' && source !== null && 'data' in source;\r\n }\r\n\r\n private isFileLike(source: DocumentSource): source is FileLike {\n return typeof source === 'object' && source !== null && typeof (source as FileLike).arrayBuffer === 'function';\n }\n\n private normalizeLoadInput(input: DocumentLoadInput): { source: DocumentSource; type?: DocumentType } {\n if (this.isLoadRequest(input)) {\n return { source: input.source, type: input.type };\n }\n return { source: input };\n }\n\n private isLoadRequest(input: DocumentLoadInput): input is DocumentLoadRequest {\n return typeof input === 'object' && input !== null && 'source' in input && 'type' in input;\n }\n\n private async resolveSource(source: DocumentSource): Promise<any> {\n if (typeof source === 'string') {\n const dataUri = this.parseDataUri(source);\n if (dataUri) {\n return dataUri.isBase64 ? this.decodeBase64(dataUri.data) : dataUri.data;\n }\n if (this.looksLikeUri(source)) {\n return source;\n }\n if (this.isLikelyBase64(source)) {\n return this.decodeBase64(source);\n }\n return source;\n }\n if (this.isUriSource(source)) return source.uri;\n if (this.isDataSource(source)) return source.data;\n if (this.isFileLike(source)) return await source.arrayBuffer();\n return source;\n }\n\n private parseDataUri(value: string): { isBase64: boolean; data: string } | null {\n const match = /^data:([^;,]+)?(;base64)?,(.*)$/.exec(value);\n if (!match) return null;\n const isBase64 = Boolean(match[2]);\n const data = match[3] ?? '';\n return { isBase64, data };\n }\n\n private decodeBase64(value: string): Uint8Array {\n const clean = value.replace(/\\s/g, '');\n if (typeof atob !== 'function') {\n throw new Error('[EPUBEngine] atob não está disponível para decodificar base64.');\n }\n const binary = atob(clean);\n const len = binary.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i += 1) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n }\n\n private looksLikeUri(value: string): boolean {\n return (\n value.startsWith('http://') ||\n value.startsWith('https://') ||\n value.startsWith('/') ||\n value.startsWith('./') ||\n value.startsWith('../') ||\n value.startsWith('file://')\n );\n }\n\n private isLikelyBase64(value: string): boolean {\n if (this.looksLikeUri(value)) return false;\n if (value.includes('.')) return false;\n if (value.length < 16) return false;\n return /^[A-Za-z0-9+/=]+$/.test(value);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAiB;AACjB,kBAAmC;AAG5B,IAAM,aAAN,cAAyB,+BAAmB;AAAA,EAA5C;AAAA;AACL,SAAQ,OAAY;AACpB,SAAQ,aAAoB,CAAC;AAC7B,SAAQ,aAAa,oBAAI,IAAiB;AAC1C,SAAQ,mBAAmB,oBAAI,IAAyB;AACxD,SAAQ,YAAY,oBAAI,IAA+C;AACvE,SAAQ,cAAsB;AAC9B,SAAQ,OAAe;AACvB,SAAQ,WAAmB;AAAA;AAAA,EAE3B,sBAAiC;AAAE,WAAO;AAAA,EAAW;AAAA,EAErD,MAAM,KAAK,OAAyC;AAClD,QAAI;AACF,YAAM,EAAE,QAAQ,KAAK,IAAI,KAAK,mBAAmB,KAAK;AACtD,UAAI,QAAQ,SAAS,QAAQ;AAC3B,cAAM,IAAI,MAAM,oDAAiD,IAAI,EAAE;AAAA,MACzE;AAEA,YAAM,OAAO,MAAM,KAAK,cAAc,MAAM;AAE5C,WAAK,WAAO,cAAAA,SAAK,IAAI;AACrB,YAAM,KAAK,KAAK;AAChB,WAAK,aAAa,KAAK,KAAK,OAAO,SAAS,CAAC;AAC7C,WAAK,cAAc;AACnB,WAAK,WAAW,QAAQ,CAAC,cAAc,WAAW,UAAU,CAAC;AAC7D,WAAK,WAAW,MAAM;AACtB,WAAK,iBAAiB,MAAM;AAC5B,WAAK,UAAU,MAAM;AAAA,IACvB,SAAS,OAAO;AACd,cAAQ,MAAM,kCAAkC,KAAK;AACrD,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,eAAuB;AAAE,WAAO,KAAK,WAAW;AAAA,EAAQ;AAAA,EACxD,iBAAyB;AAAE,WAAO,KAAK;AAAA,EAAa;AAAA,EACpD,SAAS,MAAoB;AAC3B,QAAI,QAAQ,KAAK,QAAQ,KAAK,aAAa,EAAG,MAAK,cAAc;AAAA,EACnE;AAAA,EACA,QAAQ,MAAoB;AAC1B,SAAK,OAAO,KAAK,IAAI,KAAK,KAAK,IAAI,GAAK,IAAI,CAAC;AAC7C,SAAK,WAAW,QAAQ,CAAC,cAAc,KAAK,oBAAoB,SAAS,CAAC;AAAA,EAC5E;AAAA,EACA,UAAkB;AAAE,WAAO,KAAK;AAAA,EAAM;AAAA,EAEtC,OAAO,WAAmD;AACxD,QAAI,cAAc,YAAa,MAAK,YAAY,KAAK,WAAW,MAAM;AAAA,SACjE;AAAE,WAAK,YAAY,KAAK,WAAW,MAAM;AAAK,UAAI,KAAK,WAAW,EAAG,MAAK,YAAY;AAAA,IAAK;AAAA,EAClG;AAAA,EAEA,cAAsB;AAAE,WAAO,KAAK;AAAA,EAAU;AAAA,EAE9C,MAAM,kBAAkB,WAA+D;AACrF,UAAM,OAAO,KAAK,UAAU,IAAI,SAAS;AACzC,QAAI,KAAM,QAAO;AACjB,WAAO,EAAE,OAAO,GAAG,QAAQ,EAAE;AAAA,EAC/B;AAAA,EAEA,MAAM,WACJ,WACA,MAC+B;AAC/B,SAAK;AACL,SAAK;AACL,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,WAAW,WAAmB,QAAa,OAA8B;AAC7E,UAAM,WAAW,KAAK,MAAM,QAAQ,GAAI;AACxC,UAAM,UAAU;AAChB,QAAI,CAAC,KAAK,QAAQ,CAAC,QAAS;AAE5B,UAAM,YAAY,KAAK,WAAW,SAAS;AAC3C,QAAI,CAAC,UAAW;AAEhB,UAAM,QAAQ,QAAQ,cAAc,IAAI,QAAQ,cAAc;AAC9D,UAAM,SAAS,QAAQ,eAAe,IAAI,QAAQ,eAAe;AACjE,YAAQ,MAAM,QAAQ,GAAG,KAAK;AAC9B,YAAQ,MAAM,SAAS,GAAG,MAAM;AAChC,QAAI,SAAS,OAAO,UAAU,IAAK,MAAK,UAAU,IAAI,WAAW,EAAE,OAAO,OAAO,CAAC;AAElF,UAAM,eAAe,GAAG,SAAS,IAAI,QAAQ;AAC7C,QAAI,YAAY,KAAK,WAAW,IAAI,YAAY;AAChD,UAAM,gBAAgB,KAAK,iBAAiB,IAAI,YAAY;AAC5D,QAAI,CAAC,aAAa,kBAAkB,SAAS;AAC3C,UAAI,WAAW,QAAS,WAAU,QAAQ;AAC1C,cAAQ,YAAY;AACpB,kBAAY,KAAK,KAAK,SAAS,SAAS;AAAA,QACtC;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN,QAAQ;AAAA,MACV,CAAC;AACD,WAAK,WAAW,IAAI,cAAc,SAAS;AAC3C,WAAK,iBAAiB,IAAI,cAAc,OAAO;AAC/C,UAAI,WAAW,OAAO,SAAS,UAAU;AACvC,kBAAU,MAAM,QAAQ,SAAS,CAAC,aAAkB;AAClD,gBAAM,QAAQ,UAAU,UAAU,aAAa;AAC/C,cAAI,OAAO;AACT,kBAAM,aAAa,WAAW,iCAAiC;AAAA,UACjE;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,WAAW,OAAO,UAAU,WAAW,YAAY;AACjD,gBAAU,OAAO,OAAO,MAAM;AAAA,IAChC;AAEA,QAAI,WAAW;AACb,WAAK,oBAAoB,SAAS;AAClC,YAAM,YAAY,UAAU,QAAQ,UAAU,SAAS,UAAU,WAAW;AAC5E,YAAM,UAAU,QAAQ,SAAS;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,MAAM,gBAAgB,WAAmB,WAAgB,OAA8B;AACrF,SAAK;AACL,SAAK;AACL,UAAM,UAAU;AAChB,QAAI,QAAS,SAAQ,YAAY;AAAA,EACnC;AAAA,EAEA,MAAM,eAAe,WAAwC;AAC3D,QAAI,CAAC,KAAK,KAAM,QAAO,CAAC;AACxB,UAAM,YAAY,KAAK,WAAW,SAAS;AAC3C,QAAI,CAAC,UAAW,QAAO,CAAC;AAExB,QAAI;AACF,YAAM,UAAU,KAAK,KAAK,MAAM,IAAI,UAAU,SAAS,UAAU,IAAI;AACrE,YAAM,OAAO,OAAO,SAAS,SAAS,aAAa,MAAM,QAAQ,KAAK,IAAI;AAC1E,UAAI,CAAC,KAAM,QAAO,CAAC;AACnB,aAAO,CAAC;AAAA,QACN,KAAK;AAAA,QACL,KAAK;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,WAAW,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAAA,QAC5B,UAAU;AAAA,MACZ,CAAC;AAAA,IACH,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEA,MAAM,aAAqC;AACzC,QAAI,CAAC,KAAK,KAAM,QAAO,CAAC;AACxB,UAAM,MAAM,MAAM,KAAK,KAAK,QAAQ;AACpC,UAAM,MAAM,KAAK,OAAO,CAAC;AACzB,QAAI,CAAC,IAAI,OAAQ,QAAO,CAAC;AAEzB,UAAM,UAAU,CAAC,SAA2B;AAC1C,YAAM,QAAQ,KAAK,SAAS,KAAK,SAAS;AAC1C,YAAM,YAAY,KAAK,oBAAoB,KAAK,QAAQ,EAAE;AAC1D,YAAM,WAAW,MAAM,QAAQ,KAAK,QAAQ,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC;AAC9E,YAAM,cAA2B,EAAE,OAAO,UAAU;AACpD,UAAI,SAAS,SAAS,EAAG,aAAY,WAAW;AAChD,aAAO;AAAA,IACT;AAEA,WAAO,IAAI,IAAI,OAAO;AAAA,EACxB;AAAA,EAEA,MAAM,aAAa,MAAmC;AACpD,QAAI,CAAC,KAAM,QAAO;AAClB,QAAI,OAAO,SAAS,SAAU,QAAO,KAAK,oBAAoB,IAAI;AAClE,WAAO;AAAA,EACT;AAAA,EAEA,UAAgB;AACd,SAAK,WAAW,QAAQ,CAAC,cAAc,WAAW,UAAU,CAAC;AAC7D,SAAK,WAAW,MAAM;AACtB,SAAK,iBAAiB,MAAM;AAC5B,SAAK,UAAU,MAAM;AACrB,QAAI,KAAK,MAAM,QAAS,MAAK,KAAK,QAAQ;AAC1C,SAAK,OAAO;AACZ,SAAK,aAAa,CAAC;AAAA,EACrB;AAAA,EAEQ,oBAAoB,WAAsB;AAChD,QAAI,CAAC,UAAW;AAChB,UAAM,WAAW,GAAG,KAAK,MAAM,KAAK,OAAO,GAAG,CAAC;AAC/C,QAAI,UAAU,QAAQ,UAAU;AAC9B,gBAAU,OAAO,SAAS,QAAQ;AAAA,IACpC,WAAW,UAAU,QAAQ,UAAU;AACrC,gBAAU,OAAO,SAAS,aAAa,QAAQ;AAAA,IACjD;AAAA,EACF;AAAA,EAEQ,oBAAoB,MAAsB;AAChD,UAAM,aAAa,KAAK,cAAc,IAAI;AAC1C,QAAI,CAAC,WAAY,QAAO;AACxB,UAAM,QAAQ,KAAK,WAAW,UAAU,CAAC,SAAS,KAAK,cAAc,KAAK,IAAI,MAAM,UAAU;AAC9F,WAAO;AAAA,EACT;AAAA,EAEQ,cAAc,MAAsB;AAC1C,WAAO,KAAK,MAAM,GAAG,EAAE,CAAC;AAAA,EAC1B;AAAA,EAEQ,YAAY,QAAmD;AACrE,WAAO,OAAO,WAAW,YAAY,WAAW,QAAQ,SAAS;AAAA,EACnE;AAAA,EAEQ,aAAa,QAAsE;AACzF,WAAO,OAAO,WAAW,YAAY,WAAW,QAAQ,UAAU;AAAA,EACpE;AAAA,EAEQ,WAAW,QAA4C;AAC7D,WAAO,OAAO,WAAW,YAAY,WAAW,QAAQ,OAAQ,OAAoB,gBAAgB;AAAA,EACtG;AAAA,EAEQ,mBAAmB,OAA2E;AACpG,QAAI,KAAK,cAAc,KAAK,GAAG;AAC7B,aAAO,EAAE,QAAQ,MAAM,QAAQ,MAAM,MAAM,KAAK;AAAA,IAClD;AACA,WAAO,EAAE,QAAQ,MAAM;AAAA,EACzB;AAAA,EAEQ,cAAc,OAAwD;AAC5E,WAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,YAAY,SAAS,UAAU;AAAA,EACvF;AAAA,EAEA,MAAc,cAAc,QAAsC;AAChE,QAAI,OAAO,WAAW,UAAU;AAC9B,YAAM,UAAU,KAAK,aAAa,MAAM;AACxC,UAAI,SAAS;AACX,eAAO,QAAQ,WAAW,KAAK,aAAa,QAAQ,IAAI,IAAI,QAAQ;AAAA,MACtE;AACA,UAAI,KAAK,aAAa,MAAM,GAAG;AAC7B,eAAO;AAAA,MACT;AACA,UAAI,KAAK,eAAe,MAAM,GAAG;AAC/B,eAAO,KAAK,aAAa,MAAM;AAAA,MACjC;AACA,aAAO;AAAA,IACT;AACA,QAAI,KAAK,YAAY,MAAM,EAAG,QAAO,OAAO;AAC5C,QAAI,KAAK,aAAa,MAAM,EAAG,QAAO,OAAO;AAC7C,QAAI,KAAK,WAAW,MAAM,EAAG,QAAO,MAAM,OAAO,YAAY;AAC7D,WAAO;AAAA,EACT;AAAA,EAEQ,aAAa,OAA2D;AAC9E,UAAM,QAAQ,kCAAkC,KAAK,KAAK;AAC1D,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,WAAW,QAAQ,MAAM,CAAC,CAAC;AACjC,UAAM,OAAO,MAAM,CAAC,KAAK;AACzB,WAAO,EAAE,UAAU,KAAK;AAAA,EAC1B;AAAA,EAEQ,aAAa,OAA2B;AAC9C,UAAM,QAAQ,MAAM,QAAQ,OAAO,EAAE;AACrC,QAAI,OAAO,SAAS,YAAY;AAC9B,YAAM,IAAI,MAAM,yEAAgE;AAAA,IAClF;AACA,UAAM,SAAS,KAAK,KAAK;AACzB,UAAM,MAAM,OAAO;AACnB,UAAM,QAAQ,IAAI,WAAW,GAAG;AAChC,aAAS,IAAI,GAAG,IAAI,KAAK,KAAK,GAAG;AAC/B,YAAM,CAAC,IAAI,OAAO,WAAW,CAAC;AAAA,IAChC;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,aAAa,OAAwB;AAC3C,WACE,MAAM,WAAW,SAAS,KAC1B,MAAM,WAAW,UAAU,KAC3B,MAAM,WAAW,GAAG,KACpB,MAAM,WAAW,IAAI,KACrB,MAAM,WAAW,KAAK,KACtB,MAAM,WAAW,SAAS;AAAA,EAE9B;AAAA,EAEQ,eAAe,OAAwB;AAC7C,QAAI,KAAK,aAAa,KAAK,EAAG,QAAO;AACrC,QAAI,MAAM,SAAS,GAAG,EAAG,QAAO;AAChC,QAAI,MAAM,SAAS,GAAI,QAAO;AAC9B,WAAO,oBAAoB,KAAK,KAAK;AAAA,EACvC;AACF;","names":["ePub"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,260 @@
1
+ // index.ts
2
+ import ePub from "epubjs";
3
+ import { BaseDocumentEngine } from "@papyrus-sdk/core";
4
+ var EPUBEngine = class extends BaseDocumentEngine {
5
+ constructor() {
6
+ super(...arguments);
7
+ this.book = null;
8
+ this.spineItems = [];
9
+ this.renditions = /* @__PURE__ */ new Map();
10
+ this.renditionTargets = /* @__PURE__ */ new Map();
11
+ this.pageSizes = /* @__PURE__ */ new Map();
12
+ this.currentPage = 1;
13
+ this.zoom = 1;
14
+ this.rotation = 0;
15
+ }
16
+ getRenderTargetType() {
17
+ return "element";
18
+ }
19
+ async load(input) {
20
+ try {
21
+ const { source, type } = this.normalizeLoadInput(input);
22
+ if (type && type !== "epub") {
23
+ throw new Error(`[EPUBEngine] Tipo de documento n\xE3o suportado: ${type}`);
24
+ }
25
+ const data = await this.resolveSource(source);
26
+ this.book = ePub(data);
27
+ await this.book.ready;
28
+ this.spineItems = this.book.spine?.items ?? [];
29
+ this.currentPage = 1;
30
+ this.renditions.forEach((rendition) => rendition?.destroy?.());
31
+ this.renditions.clear();
32
+ this.renditionTargets.clear();
33
+ this.pageSizes.clear();
34
+ } catch (error) {
35
+ console.error("[EPUBEngine] Erro ao carregar:", error);
36
+ throw error;
37
+ }
38
+ }
39
+ getPageCount() {
40
+ return this.spineItems.length;
41
+ }
42
+ getCurrentPage() {
43
+ return this.currentPage;
44
+ }
45
+ goToPage(page) {
46
+ if (page >= 1 && page <= this.getPageCount()) this.currentPage = page;
47
+ }
48
+ setZoom(zoom) {
49
+ this.zoom = Math.max(0.5, Math.min(3, zoom));
50
+ this.renditions.forEach((rendition) => this.applyRenditionTheme(rendition));
51
+ }
52
+ getZoom() {
53
+ return this.zoom;
54
+ }
55
+ rotate(direction) {
56
+ if (direction === "clockwise") this.rotation = (this.rotation + 90) % 360;
57
+ else {
58
+ this.rotation = (this.rotation - 90) % 360;
59
+ if (this.rotation < 0) this.rotation += 360;
60
+ }
61
+ }
62
+ getRotation() {
63
+ return this.rotation;
64
+ }
65
+ async getPageDimensions(pageIndex) {
66
+ const size = this.pageSizes.get(pageIndex);
67
+ if (size) return size;
68
+ return { width: 0, height: 0 };
69
+ }
70
+ async selectText(pageIndex, rect) {
71
+ void pageIndex;
72
+ void rect;
73
+ return null;
74
+ }
75
+ async renderPage(pageIndex, target, scale) {
76
+ const scaleKey = Math.round(scale * 1e3);
77
+ const element = target;
78
+ if (!this.book || !element) return;
79
+ const spineItem = this.spineItems[pageIndex];
80
+ if (!spineItem) return;
81
+ const width = element.clientWidth > 0 ? element.clientWidth : 640;
82
+ const height = element.clientHeight > 0 ? element.clientHeight : 900;
83
+ element.style.width = `${width}px`;
84
+ element.style.height = `${height}px`;
85
+ if (width >= 320 && height >= 480) this.pageSizes.set(pageIndex, { width, height });
86
+ const renditionKey = `${pageIndex}:${scaleKey}`;
87
+ let rendition = this.renditions.get(renditionKey);
88
+ const currentTarget = this.renditionTargets.get(renditionKey);
89
+ if (!rendition || currentTarget !== element) {
90
+ if (rendition?.destroy) rendition.destroy();
91
+ element.innerHTML = "";
92
+ rendition = this.book.renderTo(element, {
93
+ width,
94
+ height,
95
+ flow: "paginated",
96
+ spread: "none"
97
+ });
98
+ this.renditions.set(renditionKey, rendition);
99
+ this.renditionTargets.set(renditionKey, element);
100
+ if (rendition?.hooks?.content?.register) {
101
+ rendition.hooks.content.register((contents) => {
102
+ const frame = contents?.document?.defaultView?.frameElement;
103
+ if (frame) {
104
+ frame.setAttribute("sandbox", "allow-scripts allow-same-origin");
105
+ }
106
+ });
107
+ }
108
+ } else if (typeof rendition.resize === "function") {
109
+ rendition.resize(width, height);
110
+ }
111
+ if (rendition) {
112
+ this.applyRenditionTheme(rendition);
113
+ const targetRef = spineItem.href || spineItem.idref || spineItem.cfiBase || pageIndex;
114
+ await rendition.display(targetRef);
115
+ }
116
+ }
117
+ async renderTextLayer(pageIndex, container, scale) {
118
+ void pageIndex;
119
+ void scale;
120
+ const element = container;
121
+ if (element) element.innerHTML = "";
122
+ }
123
+ async getTextContent(pageIndex) {
124
+ if (!this.book) return [];
125
+ const spineItem = this.spineItems[pageIndex];
126
+ if (!spineItem) return [];
127
+ try {
128
+ const section = this.book.spine.get(spineItem.idref || spineItem.href);
129
+ const text = typeof section?.text === "function" ? await section.text() : "";
130
+ if (!text) return [];
131
+ return [{
132
+ str: text,
133
+ dir: "ltr",
134
+ width: 0,
135
+ height: 0,
136
+ transform: [1, 0, 0, 1, 0, 0],
137
+ fontName: "default"
138
+ }];
139
+ } catch {
140
+ return [];
141
+ }
142
+ }
143
+ async getOutline() {
144
+ if (!this.book) return [];
145
+ const nav = await this.book.loaded?.navigation;
146
+ const toc = nav?.toc ?? [];
147
+ if (!toc.length) return [];
148
+ const mapItem = (item) => {
149
+ const title = item.label || item.title || "";
150
+ const pageIndex = this.getSpineIndexByHref(item.href || "");
151
+ const children = Array.isArray(item.subitems) ? item.subitems.map(mapItem) : [];
152
+ const outlineItem = { title, pageIndex };
153
+ if (children.length > 0) outlineItem.children = children;
154
+ return outlineItem;
155
+ };
156
+ return toc.map(mapItem);
157
+ }
158
+ async getPageIndex(dest) {
159
+ if (!dest) return null;
160
+ if (typeof dest === "string") return this.getSpineIndexByHref(dest);
161
+ return null;
162
+ }
163
+ destroy() {
164
+ this.renditions.forEach((rendition) => rendition?.destroy?.());
165
+ this.renditions.clear();
166
+ this.renditionTargets.clear();
167
+ this.pageSizes.clear();
168
+ if (this.book?.destroy) this.book.destroy();
169
+ this.book = null;
170
+ this.spineItems = [];
171
+ }
172
+ applyRenditionTheme(rendition) {
173
+ if (!rendition) return;
174
+ const fontSize = `${Math.round(this.zoom * 100)}%`;
175
+ if (rendition.themes?.fontSize) {
176
+ rendition.themes.fontSize(fontSize);
177
+ } else if (rendition.themes?.override) {
178
+ rendition.themes.override("font-size", fontSize);
179
+ }
180
+ }
181
+ getSpineIndexByHref(href) {
182
+ const normalized = this.normalizeHref(href);
183
+ if (!normalized) return -1;
184
+ const index = this.spineItems.findIndex((item) => this.normalizeHref(item.href) === normalized);
185
+ return index;
186
+ }
187
+ normalizeHref(href) {
188
+ return href.split("#")[0];
189
+ }
190
+ isUriSource(source) {
191
+ return typeof source === "object" && source !== null && "uri" in source;
192
+ }
193
+ isDataSource(source) {
194
+ return typeof source === "object" && source !== null && "data" in source;
195
+ }
196
+ isFileLike(source) {
197
+ return typeof source === "object" && source !== null && typeof source.arrayBuffer === "function";
198
+ }
199
+ normalizeLoadInput(input) {
200
+ if (this.isLoadRequest(input)) {
201
+ return { source: input.source, type: input.type };
202
+ }
203
+ return { source: input };
204
+ }
205
+ isLoadRequest(input) {
206
+ return typeof input === "object" && input !== null && "source" in input && "type" in input;
207
+ }
208
+ async resolveSource(source) {
209
+ if (typeof source === "string") {
210
+ const dataUri = this.parseDataUri(source);
211
+ if (dataUri) {
212
+ return dataUri.isBase64 ? this.decodeBase64(dataUri.data) : dataUri.data;
213
+ }
214
+ if (this.looksLikeUri(source)) {
215
+ return source;
216
+ }
217
+ if (this.isLikelyBase64(source)) {
218
+ return this.decodeBase64(source);
219
+ }
220
+ return source;
221
+ }
222
+ if (this.isUriSource(source)) return source.uri;
223
+ if (this.isDataSource(source)) return source.data;
224
+ if (this.isFileLike(source)) return await source.arrayBuffer();
225
+ return source;
226
+ }
227
+ parseDataUri(value) {
228
+ const match = /^data:([^;,]+)?(;base64)?,(.*)$/.exec(value);
229
+ if (!match) return null;
230
+ const isBase64 = Boolean(match[2]);
231
+ const data = match[3] ?? "";
232
+ return { isBase64, data };
233
+ }
234
+ decodeBase64(value) {
235
+ const clean = value.replace(/\s/g, "");
236
+ if (typeof atob !== "function") {
237
+ throw new Error("[EPUBEngine] atob n\xE3o est\xE1 dispon\xEDvel para decodificar base64.");
238
+ }
239
+ const binary = atob(clean);
240
+ const len = binary.length;
241
+ const bytes = new Uint8Array(len);
242
+ for (let i = 0; i < len; i += 1) {
243
+ bytes[i] = binary.charCodeAt(i);
244
+ }
245
+ return bytes;
246
+ }
247
+ looksLikeUri(value) {
248
+ return value.startsWith("http://") || value.startsWith("https://") || value.startsWith("/") || value.startsWith("./") || value.startsWith("../") || value.startsWith("file://");
249
+ }
250
+ isLikelyBase64(value) {
251
+ if (this.looksLikeUri(value)) return false;
252
+ if (value.includes(".")) return false;
253
+ if (value.length < 16) return false;
254
+ return /^[A-Za-z0-9+/=]+$/.test(value);
255
+ }
256
+ };
257
+ export {
258
+ EPUBEngine
259
+ };
260
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../index.ts"],"sourcesContent":["import ePub from 'epubjs';\r\nimport { BaseDocumentEngine } from '@papyrus-sdk/core';\nimport { DocumentLoadInput, DocumentLoadRequest, DocumentSource, DocumentType, TextItem, OutlineItem, FileLike, TextSelection } from '@papyrus-sdk/types';\n\r\nexport class EPUBEngine extends BaseDocumentEngine {\r\n private book: any = null;\r\n private spineItems: any[] = [];\r\n private renditions = new Map<string, any>();\r\n private renditionTargets = new Map<string, HTMLElement>();\r\n private pageSizes = new Map<number, { width: number; height: number }>();\r\n private currentPage: number = 1;\r\n private zoom: number = 1.0;\r\n private rotation: number = 0;\r\n\r\n getRenderTargetType(): 'element' { return 'element'; }\r\n\r\n async load(input: DocumentLoadInput): Promise<void> {\n try {\n const { source, type } = this.normalizeLoadInput(input);\n if (type && type !== 'epub') {\n throw new Error(`[EPUBEngine] Tipo de documento não suportado: ${type}`);\n }\n\n const data = await this.resolveSource(source);\n\n this.book = ePub(data);\n await this.book.ready;\n this.spineItems = this.book.spine?.items ?? [];\r\n this.currentPage = 1;\r\n this.renditions.forEach((rendition) => rendition?.destroy?.());\r\n this.renditions.clear();\r\n this.renditionTargets.clear();\r\n this.pageSizes.clear();\r\n } catch (error) {\r\n console.error('[EPUBEngine] Erro ao carregar:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n getPageCount(): number { return this.spineItems.length; }\r\n getCurrentPage(): number { return this.currentPage; }\r\n goToPage(page: number): void {\r\n if (page >= 1 && page <= this.getPageCount()) this.currentPage = page;\r\n }\r\n setZoom(zoom: number): void {\r\n this.zoom = Math.max(0.5, Math.min(3.0, zoom));\r\n this.renditions.forEach((rendition) => this.applyRenditionTheme(rendition));\r\n }\r\n getZoom(): number { return this.zoom; }\r\n\r\n rotate(direction: 'clockwise' | 'counterclockwise'): void {\r\n if (direction === 'clockwise') this.rotation = (this.rotation + 90) % 360;\r\n else { this.rotation = (this.rotation - 90) % 360; if (this.rotation < 0) this.rotation += 360; }\r\n }\r\n\r\n getRotation(): number { return this.rotation; }\r\n\r\n async getPageDimensions(pageIndex: number): Promise<{ width: number; height: number }> {\r\n const size = this.pageSizes.get(pageIndex);\r\n if (size) return size;\r\n return { width: 0, height: 0 };\r\n }\r\n\r\n async selectText(\r\n pageIndex: number,\r\n rect: { x: number; y: number; width: number; height: number }\r\n ): Promise<TextSelection | null> {\r\n void pageIndex;\r\n void rect;\r\n return null;\r\n }\r\n\r\n async renderPage(pageIndex: number, target: any, scale: number): Promise<void> {\r\n const scaleKey = Math.round(scale * 1000);\r\n const element = target as HTMLElement;\r\n if (!this.book || !element) return;\r\n\r\n const spineItem = this.spineItems[pageIndex];\r\n if (!spineItem) return;\r\n\r\n const width = element.clientWidth > 0 ? element.clientWidth : 640;\r\n const height = element.clientHeight > 0 ? element.clientHeight : 900;\r\n element.style.width = `${width}px`;\r\n element.style.height = `${height}px`;\r\n if (width >= 320 && height >= 480) this.pageSizes.set(pageIndex, { width, height });\r\n\r\n const renditionKey = `${pageIndex}:${scaleKey}`;\r\n let rendition = this.renditions.get(renditionKey);\r\n const currentTarget = this.renditionTargets.get(renditionKey);\r\n if (!rendition || currentTarget !== element) {\r\n if (rendition?.destroy) rendition.destroy();\r\n element.innerHTML = '';\r\n rendition = this.book.renderTo(element, {\r\n width,\r\n height,\r\n flow: 'paginated',\r\n spread: 'none',\r\n });\r\n this.renditions.set(renditionKey, rendition);\r\n this.renditionTargets.set(renditionKey, element);\r\n if (rendition?.hooks?.content?.register) {\r\n rendition.hooks.content.register((contents: any) => {\r\n const frame = contents?.document?.defaultView?.frameElement as HTMLIFrameElement | null;\r\n if (frame) {\r\n frame.setAttribute('sandbox', 'allow-scripts allow-same-origin');\r\n }\r\n });\r\n }\r\n } else if (typeof rendition.resize === 'function') {\r\n rendition.resize(width, height);\r\n }\r\n\r\n if (rendition) {\r\n this.applyRenditionTheme(rendition);\r\n const targetRef = spineItem.href || spineItem.idref || spineItem.cfiBase || pageIndex;\r\n await rendition.display(targetRef);\r\n }\r\n }\r\n\r\n async renderTextLayer(pageIndex: number, container: any, scale: number): Promise<void> {\r\n void pageIndex;\r\n void scale;\r\n const element = container as HTMLElement;\r\n if (element) element.innerHTML = '';\r\n }\r\n\r\n async getTextContent(pageIndex: number): Promise<TextItem[]> {\r\n if (!this.book) return [];\r\n const spineItem = this.spineItems[pageIndex];\r\n if (!spineItem) return [];\r\n\r\n try {\r\n const section = this.book.spine.get(spineItem.idref || spineItem.href);\r\n const text = typeof section?.text === 'function' ? await section.text() : '';\r\n if (!text) return [];\r\n return [{\r\n str: text,\r\n dir: 'ltr',\r\n width: 0,\r\n height: 0,\r\n transform: [1, 0, 0, 1, 0, 0],\r\n fontName: 'default',\r\n }];\r\n } catch {\r\n return [];\r\n }\r\n }\r\n\r\n async getOutline(): Promise<OutlineItem[]> {\r\n if (!this.book) return [];\r\n const nav = await this.book.loaded?.navigation;\r\n const toc = nav?.toc ?? [];\r\n if (!toc.length) return [];\r\n\r\n const mapItem = (item: any): OutlineItem => {\r\n const title = item.label || item.title || '';\r\n const pageIndex = this.getSpineIndexByHref(item.href || '');\r\n const children = Array.isArray(item.subitems) ? item.subitems.map(mapItem) : [];\r\n const outlineItem: OutlineItem = { title, pageIndex };\r\n if (children.length > 0) outlineItem.children = children;\r\n return outlineItem;\r\n };\r\n\r\n return toc.map(mapItem);\r\n }\r\n\r\n async getPageIndex(dest: any): Promise<number | null> {\r\n if (!dest) return null;\r\n if (typeof dest === 'string') return this.getSpineIndexByHref(dest);\r\n return null;\r\n }\r\n\r\n destroy(): void {\r\n this.renditions.forEach((rendition) => rendition?.destroy?.());\r\n this.renditions.clear();\r\n this.renditionTargets.clear();\r\n this.pageSizes.clear();\r\n if (this.book?.destroy) this.book.destroy();\r\n this.book = null;\r\n this.spineItems = [];\r\n }\r\n\r\n private applyRenditionTheme(rendition: any): void {\r\n if (!rendition) return;\r\n const fontSize = `${Math.round(this.zoom * 100)}%`;\r\n if (rendition.themes?.fontSize) {\r\n rendition.themes.fontSize(fontSize);\r\n } else if (rendition.themes?.override) {\r\n rendition.themes.override('font-size', fontSize);\r\n }\r\n }\r\n\r\n private getSpineIndexByHref(href: string): number {\r\n const normalized = this.normalizeHref(href);\r\n if (!normalized) return -1;\r\n const index = this.spineItems.findIndex((item) => this.normalizeHref(item.href) === normalized);\r\n return index;\r\n }\r\n\r\n private normalizeHref(href: string): string {\r\n return href.split('#')[0];\r\n }\r\n\r\n private isUriSource(source: DocumentSource): source is { uri: string } {\r\n return typeof source === 'object' && source !== null && 'uri' in source;\r\n }\r\n\r\n private isDataSource(source: DocumentSource): source is { data: ArrayBuffer | Uint8Array } {\r\n return typeof source === 'object' && source !== null && 'data' in source;\r\n }\r\n\r\n private isFileLike(source: DocumentSource): source is FileLike {\n return typeof source === 'object' && source !== null && typeof (source as FileLike).arrayBuffer === 'function';\n }\n\n private normalizeLoadInput(input: DocumentLoadInput): { source: DocumentSource; type?: DocumentType } {\n if (this.isLoadRequest(input)) {\n return { source: input.source, type: input.type };\n }\n return { source: input };\n }\n\n private isLoadRequest(input: DocumentLoadInput): input is DocumentLoadRequest {\n return typeof input === 'object' && input !== null && 'source' in input && 'type' in input;\n }\n\n private async resolveSource(source: DocumentSource): Promise<any> {\n if (typeof source === 'string') {\n const dataUri = this.parseDataUri(source);\n if (dataUri) {\n return dataUri.isBase64 ? this.decodeBase64(dataUri.data) : dataUri.data;\n }\n if (this.looksLikeUri(source)) {\n return source;\n }\n if (this.isLikelyBase64(source)) {\n return this.decodeBase64(source);\n }\n return source;\n }\n if (this.isUriSource(source)) return source.uri;\n if (this.isDataSource(source)) return source.data;\n if (this.isFileLike(source)) return await source.arrayBuffer();\n return source;\n }\n\n private parseDataUri(value: string): { isBase64: boolean; data: string } | null {\n const match = /^data:([^;,]+)?(;base64)?,(.*)$/.exec(value);\n if (!match) return null;\n const isBase64 = Boolean(match[2]);\n const data = match[3] ?? '';\n return { isBase64, data };\n }\n\n private decodeBase64(value: string): Uint8Array {\n const clean = value.replace(/\\s/g, '');\n if (typeof atob !== 'function') {\n throw new Error('[EPUBEngine] atob não está disponível para decodificar base64.');\n }\n const binary = atob(clean);\n const len = binary.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i += 1) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n }\n\n private looksLikeUri(value: string): boolean {\n return (\n value.startsWith('http://') ||\n value.startsWith('https://') ||\n value.startsWith('/') ||\n value.startsWith('./') ||\n value.startsWith('../') ||\n value.startsWith('file://')\n );\n }\n\n private isLikelyBase64(value: string): boolean {\n if (this.looksLikeUri(value)) return false;\n if (value.includes('.')) return false;\n if (value.length < 16) return false;\n return /^[A-Za-z0-9+/=]+$/.test(value);\n }\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@papyrus-sdk/engine-epub",
3
+ "version": "0.1.1",
4
+ "main": "dist/index.js",
5
+ "module": "dist/index.mjs",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "scripts": {
21
+ "build": "tsup index.ts --dts --format cjs,esm --out-dir dist --clean --sourcemap"
22
+ },
23
+ "dependencies": {
24
+ "@papyrus-sdk/core": "0.1.1",
25
+ "@papyrus-sdk/types": "0.1.1",
26
+ "epubjs": "^0.3.92"
27
+ }
28
+ }