react-book-reader 1.1.7 → 1.1.9

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.
@@ -1,960 +0,0 @@
1
- const T = (i) => {
2
- if (!i) return "";
3
- const t = document.createElement("textarea");
4
- return t.innerHTML = i, t.value;
5
- }, E = {
6
- XML: "application/xml",
7
- XHTML: "application/xhtml+xml",
8
- HTML: "text/html",
9
- CSS: "text/css",
10
- SVG: "image/svg+xml"
11
- }, J = {
12
- name: [0, 32, "string"],
13
- type: [60, 4, "string"],
14
- creator: [64, 4, "string"],
15
- numRecords: [76, 2, "uint"]
16
- }, Q = {
17
- compression: [0, 2, "uint"],
18
- numTextRecords: [8, 2, "uint"],
19
- recordSize: [10, 2, "uint"],
20
- encryption: [12, 2, "uint"]
21
- }, tt = {
22
- magic: [16, 4, "string"],
23
- length: [20, 4, "uint"],
24
- type: [24, 4, "uint"],
25
- encoding: [28, 4, "uint"],
26
- uid: [32, 4, "uint"],
27
- version: [36, 4, "uint"],
28
- titleOffset: [84, 4, "uint"],
29
- titleLength: [88, 4, "uint"],
30
- localeRegion: [94, 1, "uint"],
31
- localeLanguage: [95, 1, "uint"],
32
- resourceStart: [108, 4, "uint"],
33
- huffcdic: [112, 4, "uint"],
34
- numHuffcdic: [116, 4, "uint"],
35
- exthFlag: [128, 4, "uint"],
36
- trailingFlags: [240, 4, "uint"],
37
- indx: [244, 4, "uint"]
38
- }, et = {
39
- resourceStart: [108, 4, "uint"],
40
- fdst: [192, 4, "uint"],
41
- numFdst: [196, 4, "uint"],
42
- frag: [248, 4, "uint"],
43
- skel: [252, 4, "uint"],
44
- guide: [260, 4, "uint"]
45
- }, st = {
46
- magic: [0, 4, "string"],
47
- length: [4, 4, "uint"],
48
- count: [8, 4, "uint"]
49
- }, G = {
50
- magic: [0, 4, "string"],
51
- length: [4, 4, "uint"],
52
- type: [8, 4, "uint"],
53
- idxt: [20, 4, "uint"],
54
- numRecords: [24, 4, "uint"],
55
- encoding: [28, 4, "uint"],
56
- language: [32, 4, "uint"],
57
- total: [36, 4, "uint"],
58
- ordt: [40, 4, "uint"],
59
- ligt: [44, 4, "uint"],
60
- numLigt: [48, 4, "uint"],
61
- numCncx: [52, 4, "uint"]
62
- }, nt = {
63
- magic: [0, 4, "string"],
64
- length: [4, 4, "uint"],
65
- numControlBytes: [8, 4, "uint"]
66
- }, rt = {
67
- magic: [0, 4, "string"],
68
- offset1: [8, 4, "uint"],
69
- offset2: [12, 4, "uint"]
70
- }, it = {
71
- magic: [0, 4, "string"],
72
- length: [4, 4, "uint"],
73
- numEntries: [8, 4, "uint"],
74
- codeLength: [12, 4, "uint"]
75
- }, ot = {
76
- magic: [0, 4, "string"],
77
- numEntries: [8, 4, "uint"]
78
- }, at = {
79
- flags: [8, 4, "uint"],
80
- dataStart: [12, 4, "uint"],
81
- keyLength: [16, 4, "uint"],
82
- keyStart: [20, 4, "uint"]
83
- }, ct = {
84
- 1252: "windows-1252",
85
- 65001: "utf-8"
86
- }, j = {
87
- 100: ["creator", "string", !0],
88
- 101: ["publisher"],
89
- 103: ["description"],
90
- 104: ["isbn"],
91
- 105: ["subject", "string", !0],
92
- 106: ["date"],
93
- 108: ["contributor", "string", !0],
94
- 109: ["rights"],
95
- 110: ["subjectCode", "string", !0],
96
- 112: ["source", "string", !0],
97
- 113: ["asin"],
98
- 121: ["boundary", "uint"],
99
- 122: ["fixedLayout"],
100
- 125: ["numResources", "uint"],
101
- 126: ["originalResolution"],
102
- 127: ["zeroGutter"],
103
- 128: ["zeroMargin"],
104
- 129: ["coverURI"],
105
- 132: ["regionMagnification"],
106
- 201: ["coverOffset", "uint"],
107
- 202: ["thumbnailOffset", "uint"],
108
- 503: ["title"],
109
- 524: ["language", "string", !0],
110
- 527: ["pageProgressionDirection"]
111
- }, lt = {
112
- 1: [
113
- "ar",
114
- "ar-SA",
115
- "ar-IQ",
116
- "ar-EG",
117
- "ar-LY",
118
- "ar-DZ",
119
- "ar-MA",
120
- "ar-TN",
121
- "ar-OM",
122
- "ar-YE",
123
- "ar-SY",
124
- "ar-JO",
125
- "ar-LB",
126
- "ar-KW",
127
- "ar-AE",
128
- "ar-BH",
129
- "ar-QA"
130
- ],
131
- 2: ["bg"],
132
- 3: ["ca"],
133
- 4: ["zh", "zh-TW", "zh-CN", "zh-HK", "zh-SG"],
134
- 5: ["cs"],
135
- 6: ["da"],
136
- 7: ["de", "de-DE", "de-CH", "de-AT", "de-LU", "de-LI"],
137
- 8: ["el"],
138
- 9: [
139
- "en",
140
- "en-US",
141
- "en-GB",
142
- "en-AU",
143
- "en-CA",
144
- "en-NZ",
145
- "en-IE",
146
- "en-ZA",
147
- "en-JM",
148
- null,
149
- "en-BZ",
150
- "en-TT",
151
- "en-ZW",
152
- "en-PH"
153
- ],
154
- 10: [
155
- "es",
156
- "es-ES",
157
- "es-MX",
158
- null,
159
- "es-GT",
160
- "es-CR",
161
- "es-PA",
162
- "es-DO",
163
- "es-VE",
164
- "es-CO",
165
- "es-PE",
166
- "es-AR",
167
- "es-EC",
168
- "es-CL",
169
- "es-UY",
170
- "es-PY",
171
- "es-BO",
172
- "es-SV",
173
- "es-HN",
174
- "es-NI",
175
- "es-PR"
176
- ],
177
- 11: ["fi"],
178
- 12: ["fr", "fr-FR", "fr-BE", "fr-CA", "fr-CH", "fr-LU", "fr-MC"],
179
- 13: ["he"],
180
- 14: ["hu"],
181
- 15: ["is"],
182
- 16: ["it", "it-IT", "it-CH"],
183
- 17: ["ja"],
184
- 18: ["ko"],
185
- 19: ["nl", "nl-NL", "nl-BE"],
186
- 20: ["no", "nb", "nn"],
187
- 21: ["pl"],
188
- 22: ["pt", "pt-BR", "pt-PT"],
189
- 23: ["rm"],
190
- 24: ["ro"],
191
- 25: ["ru"],
192
- 26: ["hr", null, "sr"],
193
- 27: ["sk"],
194
- 28: ["sq"],
195
- 29: ["sv", "sv-SE", "sv-FI"],
196
- 30: ["th"],
197
- 31: ["tr"],
198
- 32: ["ur"],
199
- 33: ["id"],
200
- 34: ["uk"],
201
- 35: ["be"],
202
- 36: ["sl"],
203
- 37: ["et"],
204
- 38: ["lv"],
205
- 39: ["lt"],
206
- 41: ["fa"],
207
- 42: ["vi"],
208
- 43: ["hy"],
209
- 44: ["az"],
210
- 45: ["eu"],
211
- 46: ["hsb"],
212
- 47: ["mk"],
213
- 48: ["st"],
214
- 49: ["ts"],
215
- 50: ["tn"],
216
- 52: ["xh"],
217
- 53: ["zu"],
218
- 54: ["af"],
219
- 55: ["ka"],
220
- 56: ["fo"],
221
- 57: ["hi"],
222
- 58: ["mt"],
223
- 59: ["se"],
224
- 62: ["ms"],
225
- 63: ["kk"],
226
- 65: ["sw"],
227
- 67: ["uz", null, "uz-UZ"],
228
- 68: ["tt"],
229
- 69: ["bn"],
230
- 70: ["pa"],
231
- 71: ["gu"],
232
- 72: ["or"],
233
- 73: ["ta"],
234
- 74: ["te"],
235
- 75: ["kn"],
236
- 76: ["ml"],
237
- 77: ["as"],
238
- 78: ["mr"],
239
- 79: ["sa"],
240
- 82: ["cy", "cy-GB"],
241
- 83: ["gl", "gl-ES"],
242
- 87: ["kok"],
243
- 97: ["ne"],
244
- 98: ["fy"]
245
- }, _ = (i, t) => {
246
- const e = new i.constructor(i.length + t.length);
247
- return e.set(i), e.set(t, i.length), e;
248
- }, Y = (i, t, e) => {
249
- const s = new i.constructor(i.length + t.length + e.length);
250
- return s.set(i), s.set(t, i.length), s.set(e, i.length + t.length), s;
251
- }, ut = new TextDecoder(), O = (i) => ut.decode(i), y = (i) => {
252
- if (!i) return;
253
- const t = i.byteLength, e = t === 4 ? "getUint32" : t === 2 ? "getUint16" : "getUint8";
254
- return new DataView(i)[e](0);
255
- }, R = (i, t) => Object.fromEntries(Array.from(Object.entries(i)).map(([e, [s, o, n]]) => [
256
- e,
257
- (n === "string" ? O : y)(t.slice(s, s + o))
258
- ])), N = (i) => new TextDecoder(ct[i]), M = (i, t = 0) => {
259
- let e = 0, s = 0;
260
- for (const o of i.subarray(t, t + 4))
261
- if (e = e << 7 | (o & 127) >>> 0, s++, o & 128) break;
262
- return { value: e, length: s };
263
- }, ht = (i) => {
264
- let t = 0;
265
- for (const e of i.subarray(-4))
266
- e & 128 && (t = 0), t = t << 7 | e & 127;
267
- return t;
268
- }, Z = (i) => {
269
- let t = 0;
270
- for (; i > 0; i = i >> 1) (i & 1) === 1 && t++;
271
- return t;
272
- }, ft = (i) => {
273
- let t = 0;
274
- for (; (i & 1) === 0; ) i = i >> 1, t++;
275
- return t;
276
- }, dt = (i) => {
277
- let t = [];
278
- for (let e = 0; e < i.length; e++) {
279
- const s = i[e];
280
- if (s === 0) t.push(0);
281
- else if (s <= 8)
282
- for (const o of i.subarray(e + 1, (e += s) + 1))
283
- t.push(o);
284
- else if (s <= 127) t.push(s);
285
- else if (s <= 191) {
286
- const o = s << 8 | i[e++ + 1], n = (o & 16383) >>> 3, r = (o & 7) + 3;
287
- for (let c = 0; c < r; c++)
288
- t.push(t[t.length - n]);
289
- } else t.push(32, s ^ 128);
290
- }
291
- return Uint8Array.from(t);
292
- }, gt = (i, t) => {
293
- const e = t >> 3, s = t + 32, o = s >> 3;
294
- let n = 0n;
295
- for (let r = e; r <= o; r++)
296
- n = n << 8n | BigInt(i[r] ?? 0);
297
- return n >> 8n - BigInt(s & 7) & 0xffffffffn;
298
- }, mt = async (i, t) => {
299
- const e = await t(i.huffcdic), { magic: s, offset1: o, offset2: n } = R(rt, e);
300
- if (s !== "HUFF") throw new Error("Invalid HUFF record");
301
- const r = Array.from({ length: 256 }, (a, f) => o + f * 4).map((a) => y(e.slice(a, a + 4))).map((a) => [a & 128, a & 31, a >>> 8]), c = [null].concat(Array.from({ length: 32 }, (a, f) => n + f * 8).map((a) => [
302
- y(e.slice(a, a + 4)),
303
- y(e.slice(a + 4, a + 8))
304
- ])), u = [];
305
- for (let a = 1; a < i.numHuffcdic; a++) {
306
- const f = await t(i.huffcdic + a), h = R(it, f);
307
- if (h.magic !== "CDIC") throw new Error("Invalid CDIC record");
308
- const g = Math.min(1 << h.codeLength, h.numEntries - u.length), d = f.slice(h.length);
309
- for (let m = 0; m < g; m++) {
310
- const p = y(d.slice(m * 2, m * 2 + 2)), b = y(d.slice(p, p + 2)), w = b & 32767, x = b & 32768, C = new Uint8Array(
311
- d.slice(p + 2, p + 2 + w)
312
- );
313
- u.push([C, x]);
314
- }
315
- }
316
- const l = (a) => {
317
- let f = new Uint8Array();
318
- const h = a.byteLength * 8;
319
- for (let g = 0; g < h; ) {
320
- const d = Number(gt(a, g));
321
- let [m, p, b] = r[d >>> 24];
322
- if (!m) {
323
- for (; d >>> 32 - p < c[p][0]; )
324
- p += 1;
325
- b = c[p][1];
326
- }
327
- if ((g += p) > h) break;
328
- const w = b - (d >>> 32 - p);
329
- let [x, C] = u[w];
330
- C || (x = l(x), u[w] = [x, !0]), f = _(f, x);
331
- }
332
- return f;
333
- };
334
- return l;
335
- }, H = async (i, t) => {
336
- const e = await t(i), s = R(G, e);
337
- if (s.magic !== "INDX") throw new Error("Invalid INDX record");
338
- const o = N(s.encoding), n = e.slice(s.length), r = R(nt, n);
339
- if (r.magic !== "TAGX") throw new Error("Invalid TAGX section");
340
- const c = (r.length - 12) / 4, u = Array.from({ length: c }, (h, g) => new Uint8Array(n.slice(12 + g * 4, 12 + g * 4 + 4))), l = {};
341
- let a = 0;
342
- for (let h = 0; h < s.numCncx; h++) {
343
- const g = await t(i + s.numRecords + h + 1), d = new Uint8Array(g);
344
- for (let m = 0; m < d.byteLength; ) {
345
- const p = m, { value: b, length: w } = M(d, m);
346
- m += w;
347
- const x = g.slice(m, m + b);
348
- m += b, l[a + p] = o.decode(x);
349
- }
350
- a += 65536;
351
- }
352
- const f = [];
353
- for (let h = 0; h < s.numRecords; h++) {
354
- const g = await t(i + 1 + h), d = new Uint8Array(g), m = R(G, g);
355
- if (m.magic !== "INDX") throw new Error("Invalid INDX record");
356
- for (let p = 0; p < m.numRecords; p++) {
357
- const b = m.idxt + 4 + 2 * p, w = y(g.slice(b, b + 2)), x = y(g.slice(w, w + 1)), C = O(g.slice(w + 1, w + 1 + x)), U = [], z = w + 1 + x;
358
- let X = 0, A = z + r.numControlBytes;
359
- for (const [D, L, v, F] of u) {
360
- if (F & 1) {
361
- X++;
362
- continue;
363
- }
364
- const I = z + X, S = y(g.slice(I, I + 1)) & v;
365
- if (S === v)
366
- if (Z(v) > 1) {
367
- const { value: k, length: B } = M(d, A);
368
- U.push([D, null, k, L]), A += B;
369
- } else U.push([D, 1, null, L]);
370
- else U.push([D, S >> ft(v), null, L]);
371
- }
372
- const P = {};
373
- for (const [D, L, v, F] of U) {
374
- const I = [];
375
- if (L != null)
376
- for (let S = 0; S < L * F; S++) {
377
- const { value: k, length: B } = M(d, A);
378
- I.push(k), A += B;
379
- }
380
- else {
381
- let S = 0;
382
- for (; S < v; ) {
383
- const { value: k, length: B } = M(d, A);
384
- I.push(k), A += B, S += B;
385
- }
386
- }
387
- P[D] = I;
388
- }
389
- f.push({ name: C, tagMap: P });
390
- }
391
- }
392
- return { table: f, cncx: l };
393
- }, pt = async (i, t) => {
394
- const { table: e, cncx: s } = await H(i, t), o = e.map(({ tagMap: r }, c) => ({
395
- index: c,
396
- offset: r[1]?.[0],
397
- size: r[2]?.[0],
398
- label: s[r[3]] ?? "",
399
- headingLevel: r[4]?.[0],
400
- pos: r[6],
401
- parent: r[21]?.[0],
402
- firstChild: r[22]?.[0],
403
- lastChild: r[23]?.[0]
404
- })), n = (r) => (r.firstChild == null || (r.children = o.filter((c) => c.parent === r.index).map(n)), r);
405
- return o.filter((r) => r.headingLevel === 0).map(n);
406
- }, bt = (i, t) => {
407
- const { magic: e, count: s } = R(st, i);
408
- if (e !== "EXTH") throw new Error("Invalid EXTH header");
409
- const o = N(t), n = {};
410
- let r = 12;
411
- for (let c = 0; c < s; c++) {
412
- const u = y(i.slice(r, r + 4)), l = y(i.slice(r + 4, r + 8));
413
- if (u in j) {
414
- const [a, f, h] = j[u], g = i.slice(r + 8, r + l), d = f === "uint" ? y(g) : o.decode(g);
415
- h ? (n[a] ??= [], n[a].push(d)) : n[a] = d;
416
- }
417
- r += l;
418
- }
419
- return n;
420
- }, wt = async (i, t) => {
421
- const { flags: e, dataStart: s, keyLength: o, keyStart: n } = R(at, i), r = new Uint8Array(i.slice(s));
422
- if (e & 2) {
423
- const u = o === 16 ? 1024 : 1040, l = new Uint8Array(i.slice(n, n + o)), a = Math.min(u, r.length);
424
- for (var c = 0; c < a; c++) r[c] = r[c] ^ l[c % l.length];
425
- }
426
- if (e & 1) try {
427
- return await t(r);
428
- } catch (u) {
429
- console.warn(u), console.warn("Failed to decompress font");
430
- }
431
- return r;
432
- }, Bt = async (i) => O(await i.slice(60, 68).arrayBuffer()) === "BOOKMOBI";
433
- class yt {
434
- #t;
435
- #e;
436
- pdb;
437
- async open(t) {
438
- this.#t = t;
439
- const e = R(J, await t.slice(0, 78).arrayBuffer());
440
- this.pdb = e;
441
- const s = await t.slice(78, 78 + e.numRecords * 8).arrayBuffer();
442
- this.#e = Array.from(
443
- { length: e.numRecords },
444
- (o, n) => y(s.slice(n * 8, n * 8 + 4))
445
- ).map((o, n, r) => [o, r[n + 1]]);
446
- }
447
- loadRecord(t) {
448
- const e = this.#e[t];
449
- if (!e) throw new RangeError("Record index out of bounds");
450
- return this.#t.slice(...e).arrayBuffer();
451
- }
452
- async loadMagic(t) {
453
- const e = this.#e[t][0];
454
- return O(await this.#t.slice(e, e + 4).arrayBuffer());
455
- }
456
- }
457
- class Ct extends yt {
458
- #t = 0;
459
- #e;
460
- #n;
461
- #s;
462
- #r;
463
- #i;
464
- constructor({ unzlib: t }) {
465
- super(), this.unzlib = t;
466
- }
467
- async open(t) {
468
- await super.open(t), this.headers = this.#o(await super.loadRecord(0)), this.#e = this.headers.mobi.resourceStart;
469
- let e = this.headers.mobi.version >= 8;
470
- if (!e) {
471
- const s = this.headers.exth?.boundary;
472
- if (s < 4294967295) try {
473
- this.headers = this.#o(await super.loadRecord(s)), this.#t = s, e = !0;
474
- } catch (o) {
475
- console.warn(o), console.warn("Failed to open KF8; falling back to MOBI");
476
- }
477
- }
478
- return await this.#a(), e ? new It(this).init() : new St(this).init();
479
- }
480
- #o(t) {
481
- const e = R(Q, t), s = R(tt, t);
482
- if (s.magic !== "MOBI") throw new Error("Missing MOBI header");
483
- const { titleOffset: o, titleLength: n, localeLanguage: r, localeRegion: c } = s;
484
- s.title = t.slice(o, o + n);
485
- const u = lt[r];
486
- s.language = u?.[c >> 2] ?? u?.[0];
487
- const l = s.exthFlag & 64 ? bt(t.slice(s.length + 16), s.encoding) : null, a = s.version >= 8 ? R(et, t) : null;
488
- return { palmdoc: e, mobi: s, exth: l, kf8: a };
489
- }
490
- async #a() {
491
- const { palmdoc: t, mobi: e } = this.headers;
492
- this.#n = N(e.encoding), this.#s = new TextEncoder();
493
- const { compression: s } = t;
494
- if (this.#r = s === 1 ? (c) => c : s === 2 ? dt : s === 17480 ? await mt(e, this.loadRecord.bind(this)) : null, !this.#r) throw new Error("Unknown compression type");
495
- const { trailingFlags: o } = e, n = o & 1, r = Z(o >>> 1);
496
- this.#i = (c) => {
497
- for (let u = 0; u < r; u++) {
498
- const l = ht(c);
499
- c = c.subarray(0, -l);
500
- }
501
- if (n) {
502
- const u = (c[c.length - 1] & 3) + 1;
503
- c = c.subarray(0, -u);
504
- }
505
- return c;
506
- };
507
- }
508
- decode(...t) {
509
- return this.#n.decode(...t);
510
- }
511
- encode(...t) {
512
- return this.#s.encode(...t);
513
- }
514
- loadRecord(t) {
515
- return super.loadRecord(this.#t + t);
516
- }
517
- loadMagic(t) {
518
- return super.loadMagic(this.#t + t);
519
- }
520
- loadText(t) {
521
- return this.loadRecord(t + 1).then((e) => new Uint8Array(e)).then(this.#i).then(this.#r);
522
- }
523
- async loadResource(t) {
524
- const e = await super.loadRecord(this.#e + t), s = O(e.slice(0, 4));
525
- return s === "FONT" ? wt(e, this.unzlib) : s === "VIDE" || s === "AUDI" ? e.slice(12) : e;
526
- }
527
- getNCX() {
528
- const t = this.headers.mobi.indx;
529
- if (t < 4294967295) return pt(t, this.loadRecord.bind(this));
530
- }
531
- getMetadata() {
532
- const { mobi: t, exth: e } = this.headers;
533
- return {
534
- identifier: t.uid.toString(),
535
- title: T(e?.title || this.decode(t.title)),
536
- author: e?.creator?.map(T),
537
- publisher: T(e?.publisher),
538
- language: e?.language ?? t.language,
539
- published: e?.date,
540
- description: T(e?.description),
541
- subject: e?.subject?.map(T),
542
- rights: T(e?.rights),
543
- contributor: e?.contributor
544
- };
545
- }
546
- async getCover() {
547
- const { exth: t } = this.headers, e = t?.coverOffset < 4294967295 ? t?.coverOffset : t?.thumbnailOffset < 4294967295 ? t?.thumbnailOffset : null;
548
- if (e != null) {
549
- const s = await this.loadResource(e);
550
- return new Blob([s]);
551
- }
552
- }
553
- }
554
- const $ = /<\s*(?:mbp:)?pagebreak[^>]*>/gi, Rt = /<[^<>]+filepos=['"]{0,1}(\d+)[^<>]*>/gi, xt = (i) => {
555
- let t = 0;
556
- for (; i; ) {
557
- const e = i.parentElement;
558
- if (e) {
559
- const s = e.tagName.toLowerCase();
560
- s === "p" ? t += 1.5 : s === "blockquote" && (t += 2);
561
- }
562
- i = e;
563
- }
564
- return t;
565
- };
566
- function Et(i) {
567
- let e = "";
568
- for (let s = 0; s < i.length; s += 32768)
569
- e += String.fromCharCode.apply(null, i.subarray(s, s + 32768));
570
- return e;
571
- }
572
- class St {
573
- parser = new DOMParser();
574
- serializer = new XMLSerializer();
575
- #t = /* @__PURE__ */ new Map();
576
- #e = /* @__PURE__ */ new Map();
577
- #n = /* @__PURE__ */ new Map();
578
- #s;
579
- #r = [];
580
- #i = E.HTML;
581
- constructor(t) {
582
- this.mobi = t;
583
- }
584
- async init() {
585
- const t = [];
586
- for (let n = 0; n < this.mobi.headers.palmdoc.numTextRecords; n++) {
587
- const r = await this.mobi.loadText(n);
588
- t.push(r);
589
- }
590
- const e = t.reduce((n, r) => n + r.byteLength, 0), s = new Uint8Array(e);
591
- t.reduce((n, r) => (s.set(new Uint8Array(r), n), n + r.byteLength), 0);
592
- const o = Et(s);
593
- this.#s = [0].concat(Array.from(o.matchAll($), (n) => n.index)).map((n, r, c) => {
594
- const u = c[r + 1] ?? s.length;
595
- return { book: this, raw: s.subarray(n, u) };
596
- }).map((n, r, c) => (n.start = c[r - 1]?.end ?? 0, n.end = n.start + n.raw.byteLength, n)), this.sections = this.#s.map((n, r) => ({
597
- id: r,
598
- load: () => this.loadSection(n),
599
- createDocument: () => this.createDocument(n),
600
- size: n.end - n.start
601
- }));
602
- try {
603
- this.landmarks = await this.getGuide();
604
- const n = this.landmarks.find(({ type: r }) => r?.includes("toc"))?.href;
605
- if (n) {
606
- const { index: r } = this.resolveHref(n), c = await this.sections[r].createDocument();
607
- let u, l = 0, a = 0;
608
- const f = /* @__PURE__ */ new Map(), h = /* @__PURE__ */ new Map();
609
- this.toc = Array.from(c.querySelectorAll("a[filepos]")).reduce((g, d) => {
610
- const m = xt(d), p = {
611
- label: d.innerText?.trim() ?? "",
612
- href: `filepos:${d.getAttribute("filepos")}`
613
- }, b = m > a ? l + 1 : m === a ? l : f.get(m) ?? Math.max(0, l - 1);
614
- if (b > l)
615
- u ? (u.subitems ??= [], u.subitems.push(p), h.set(b, u)) : g.push(p);
616
- else {
617
- const w = h.get(b);
618
- w ? w.subitems.push(p) : g.push(p);
619
- }
620
- return u = p, l = b, a = m, f.set(m, b), g;
621
- }, []);
622
- }
623
- } catch (n) {
624
- console.warn(n);
625
- }
626
- return this.#r = [...new Set(
627
- Array.from(o.matchAll(Rt), (n) => n[1])
628
- )].map((n) => ({ filepos: n, number: Number(n) })).sort((n, r) => n.number - r.number), this.metadata = this.mobi.getMetadata(), this.getCover = this.mobi.getCover.bind(this.mobi), this;
629
- }
630
- async getGuide() {
631
- const t = await this.createDocument(this.#s[0]);
632
- return Array.from(t.getElementsByTagName("reference"), (e) => ({
633
- label: e.getAttribute("title"),
634
- type: e.getAttribute("type")?.split(/\s/),
635
- href: `filepos:${e.getAttribute("filepos")}`
636
- }));
637
- }
638
- async loadResource(t) {
639
- if (this.#t.has(t)) return this.#t.get(t);
640
- const e = await this.mobi.loadResource(t), s = URL.createObjectURL(new Blob([e]));
641
- return this.#t.set(t, s), s;
642
- }
643
- async loadRecindex(t) {
644
- return this.loadResource(Number(t) - 1);
645
- }
646
- async replaceResources(t) {
647
- for (const e of t.querySelectorAll("img[recindex]")) {
648
- const s = e.getAttribute("recindex");
649
- try {
650
- e.src = await this.loadRecindex(s);
651
- } catch {
652
- console.warn(`Failed to load image ${s}`);
653
- }
654
- }
655
- for (const e of t.querySelectorAll("[mediarecindex]")) {
656
- const s = e.getAttribute("mediarecindex"), o = e.getAttribute("recindex");
657
- try {
658
- e.src = await this.loadRecindex(s), o && (e.poster = await this.loadRecindex(o));
659
- } catch {
660
- console.warn(`Failed to load media ${s}`);
661
- }
662
- }
663
- for (const e of t.querySelectorAll("[filepos]")) {
664
- const s = e.getAttribute("filepos");
665
- e.href = `filepos:${s}`;
666
- }
667
- }
668
- async loadText(t) {
669
- if (this.#e.has(t)) return this.#e.get(t);
670
- const { raw: e } = t, s = this.#r.filter(({ number: r }) => r >= t.start && r < t.end).map((r) => ({ ...r, offset: r.number - t.start }));
671
- let o = e;
672
- s.length && (o = e.subarray(0, s[0].offset), s.forEach(({ filepos: r, offset: c }, u) => {
673
- const l = s[u + 1], a = this.mobi.encode(`<a id="filepos${r}"></a>`);
674
- o = Y(o, a, e.subarray(c, l?.offset));
675
- }));
676
- const n = this.mobi.decode(o).replaceAll($, "");
677
- return this.#e.set(t, n), n;
678
- }
679
- async createDocument(t) {
680
- const e = await this.loadText(t);
681
- return this.parser.parseFromString(e, this.#i);
682
- }
683
- async loadSection(t) {
684
- if (this.#n.has(t)) return this.#n.get(t);
685
- const e = await this.createDocument(t), s = e.createElement("style");
686
- e.head.append(s), s.append(e.createTextNode(`blockquote {
687
- margin-block-start: 0;
688
- margin-block-end: 0;
689
- margin-inline-start: 1em;
690
- margin-inline-end: 0;
691
- }`)), await this.replaceResources(e);
692
- const o = this.serializer.serializeToString(e), n = URL.createObjectURL(new Blob([o], { type: this.#i }));
693
- return this.#n.set(t, n), n;
694
- }
695
- resolveHref(t) {
696
- const e = t.match(/filepos:(.*)/)[1], s = Number(e);
697
- return { index: this.#s.findIndex((r) => r.end > s), anchor: (r) => r.getElementById(`filepos${e}`) };
698
- }
699
- splitTOCHref(t) {
700
- const e = t.match(/filepos:(.*)/)[1], s = Number(e);
701
- return [this.#s.findIndex((n) => n.end > s), `filepos${e}`];
702
- }
703
- getTOCFragment(t, e) {
704
- return t.getElementById(e);
705
- }
706
- isExternal(t) {
707
- return /^(?!blob|filepos)\w+:/i.test(t);
708
- }
709
- destroy() {
710
- for (const t of this.#t.values()) URL.revokeObjectURL(t);
711
- for (const t of this.#n.values()) URL.revokeObjectURL(t);
712
- }
713
- }
714
- const W = /kindle:(flow|embed):(\w+)(?:\?mime=(\w+\/[-+.\w]+))?/, Tt = /kindle:pos:fid:(\w+):off:(\w+)/, At = (i) => {
715
- const [t, e, s] = i.match(W).slice(1);
716
- return { resourceType: t, id: parseInt(e, 32), type: s };
717
- }, q = (i) => {
718
- const [t, e] = i.match(Tt).slice(1);
719
- return { fid: parseInt(t, 32), off: parseInt(e, 32) };
720
- }, V = (i = 0, t = 0) => `kindle:pos:fid:${i.toString(32).toUpperCase().padStart(4, "0")}:off:${t.toString(32).toUpperCase().padStart(10, "0")}`, K = (i) => {
721
- const t = i.match(/\s(id|name|aid)\s*=\s*['"]([^'"]*)['"]/i);
722
- if (!t) return;
723
- const [, e, s] = t;
724
- return `[${e}="${CSS.escape(s)}"]`;
725
- }, Lt = async (i, t, e) => {
726
- const s = [];
727
- i.replace(t, (...n) => (s.push(n), null));
728
- const o = [];
729
- for (const n of s) o.push(await e(...n));
730
- return i.replace(t, () => o.shift());
731
- }, vt = (i) => {
732
- for (const t of i) {
733
- if (t === "page-spread-left" || t === "rendition:page-spread-left")
734
- return "left";
735
- if (t === "page-spread-right" || t === "rendition:page-spread-right")
736
- return "right";
737
- if (t === "rendition:page-spread-center") return "center";
738
- }
739
- };
740
- class It {
741
- parser = new DOMParser();
742
- serializer = new XMLSerializer();
743
- transformTarget = new EventTarget();
744
- #t = /* @__PURE__ */ new Map();
745
- #e = /* @__PURE__ */ new Map();
746
- #n = /* @__PURE__ */ new Map();
747
- #s = {};
748
- #r;
749
- #i;
750
- #o = new Uint8Array();
751
- #a = new Uint8Array();
752
- #h = -1;
753
- #f = -1;
754
- #c = E.XHTML;
755
- #l = /* @__PURE__ */ new Map();
756
- constructor(t) {
757
- this.mobi = t;
758
- }
759
- async init() {
760
- const t = this.mobi.loadRecord.bind(this.mobi), { kf8: e } = this.mobi.headers;
761
- try {
762
- const l = await t(e.fdst), a = R(ot, l);
763
- if (a.magic !== "FDST") throw new Error("Missing FDST record");
764
- const f = Array.from(
765
- { length: a.numEntries },
766
- (h, g) => 12 + g * 8
767
- ).map((h) => [
768
- y(l.slice(h, h + 4)),
769
- y(l.slice(h + 4, h + 8))
770
- ]);
771
- this.#s.fdstTable = f, this.#i = f[f.length - 1][1];
772
- } catch {
773
- }
774
- const s = (await H(e.skel, t)).table.map(({ name: l, tagMap: a }, f) => ({
775
- index: f,
776
- name: l,
777
- numFrag: a[1][0],
778
- offset: a[6][0],
779
- length: a[6][1]
780
- })), o = await H(e.frag, t), n = o.table.map(({ name: l, tagMap: a }) => ({
781
- insertOffset: parseInt(l),
782
- selector: o.cncx[a[2][0]],
783
- index: a[4][0],
784
- offset: a[6][0],
785
- length: a[6][1]
786
- }));
787
- this.#s.skelTable = s, this.#s.fragTable = n, this.#r = s.reduce((l, a) => {
788
- const f = l[l.length - 1], h = f?.fragEnd ?? 0, g = h + a.numFrag, d = n.slice(h, g), m = a.length + d.map((b) => b.length).reduce((b, w) => b + w, 0), p = (f?.totalLength ?? 0) + m;
789
- return l.concat({ skel: a, frags: d, fragEnd: g, length: m, totalLength: p });
790
- }, []);
791
- const r = await this.getResourcesByMagic(["RESC", "PAGE"]), c = /* @__PURE__ */ new Map();
792
- if (r.RESC) {
793
- const l = await this.mobi.loadRecord(r.RESC), a = this.mobi.decode(l.slice(16)).replace(/\0/g, ""), f = a.search(/\?>/), h = `<package>${a.slice(f)}</package>`, g = this.parser.parseFromString(h, E.XML);
794
- for (const d of g.querySelectorAll("spine > itemref")) {
795
- const m = parseInt(d.getAttribute("skelid"));
796
- c.set(m, vt(
797
- d.getAttribute("properties")?.split(" ") ?? []
798
- ));
799
- }
800
- }
801
- this.sections = this.#r.map((l, a) => l.frags.length ? {
802
- id: a,
803
- load: () => this.loadSection(l),
804
- createDocument: () => this.createDocument(l),
805
- size: l.length,
806
- pageSpread: c.get(a)
807
- } : { linear: "no" });
808
- try {
809
- const l = await this.mobi.getNCX(), a = ({ label: f, pos: h, children: g }) => {
810
- const [d, m] = h, p = V(d, m), b = this.#e.get(d);
811
- return b ? b.push(m) : this.#e.set(d, [m]), { label: T(f), href: p, subitems: g?.map(a) };
812
- };
813
- this.toc = l?.map(a), this.landmarks = await this.getGuide();
814
- } catch (l) {
815
- console.warn(l);
816
- }
817
- const { exth: u } = this.mobi.headers;
818
- return this.dir = u.pageProgressionDirection, this.rendition = {
819
- layout: u.fixedLayout === "true" ? "pre-paginated" : "reflowable",
820
- viewport: Object.fromEntries(u.originalResolution?.split("x")?.slice(0, 2)?.map((l, a) => [a ? "height" : "width", l]) ?? [])
821
- }, this.metadata = this.mobi.getMetadata(), this.getCover = this.mobi.getCover.bind(this.mobi), this;
822
- }
823
- // is this really the only way of getting to RESC, PAGE, etc.?
824
- async getResourcesByMagic(t) {
825
- const e = {}, s = this.mobi.headers.kf8.resourceStart, o = this.mobi.pdb.numRecords;
826
- for (let n = s; n < o; n++)
827
- try {
828
- const r = await this.mobi.loadMagic(n), c = t.find((u) => u === r);
829
- c && (e[c] = n);
830
- } catch {
831
- }
832
- return e;
833
- }
834
- async getGuide() {
835
- const t = this.mobi.headers.kf8.guide;
836
- if (t < 4294967295) {
837
- const e = this.mobi.loadRecord.bind(this.mobi), { table: s, cncx: o } = await H(t, e);
838
- return s.map(({ name: n, tagMap: r }) => ({
839
- label: o[r[1][0]] ?? "",
840
- type: n?.split(/\s/),
841
- href: V(r[6]?.[0] ?? r[3]?.[0])
842
- }));
843
- }
844
- }
845
- async loadResourceBlob(t) {
846
- const { resourceType: e, id: s, type: o } = At(t), n = e === "flow" ? await this.loadFlow(s) : await this.mobi.loadResource(s - 1), c = { data: [E.XHTML, E.HTML, E.CSS, E.SVG].includes(o) ? await this.replaceResources(this.mobi.decode(n)) : n, type: o }, u = new CustomEvent("data", { detail: c });
847
- this.transformTarget.dispatchEvent(u);
848
- const l = await u.detail.data, a = await u.detail.type, f = a === E.SVG ? this.parser.parseFromString(l, a) : null;
849
- return [
850
- new Blob([l], { newType: a }),
851
- // SVG wrappers need to be inlined
852
- // as browsers don't allow external resources when loading SVG as an image
853
- f?.getElementsByTagNameNS("http://www.w3.org/2000/svg", "image")?.length ? f.documentElement : null
854
- ];
855
- }
856
- async loadResource(t) {
857
- if (this.#t.has(t)) return this.#t.get(t);
858
- const [e, s] = await this.loadResourceBlob(t), o = s ? t : URL.createObjectURL(e);
859
- return s && this.#l.set(o, s), this.#t.set(t, o), o;
860
- }
861
- replaceResources(t) {
862
- const e = new RegExp(W, "g");
863
- return Lt(t, e, this.loadResource.bind(this));
864
- }
865
- // NOTE: there doesn't seem to be a way to access text randomly?
866
- // how to know the decompressed size of the records without decompressing?
867
- // 4096 is just the maximum size
868
- async loadRaw(t, e) {
869
- const s = e - this.#o.length, o = this.#i == null ? 1 / 0 : this.#i - this.#a.length - t;
870
- if (s < 0 || s < o) {
871
- for (; this.#o.length < e; ) {
872
- const r = ++this.#h, c = await this.mobi.loadText(r);
873
- this.#o = _(this.#o, c);
874
- }
875
- return this.#o.slice(t, e);
876
- }
877
- for (; this.#i - this.#a.length > t; ) {
878
- const r = this.mobi.headers.palmdoc.numTextRecords - 1 - ++this.#f, c = await this.mobi.loadText(r);
879
- this.#a = _(c, this.#a);
880
- }
881
- const n = this.#i - this.#a.length;
882
- return this.#a.slice(t - n, e - n);
883
- }
884
- loadFlow(t) {
885
- if (t < 4294967295)
886
- return this.loadRaw(...this.#s.fdstTable[t]);
887
- }
888
- async loadText(t) {
889
- const { skel: e, frags: s, length: o } = t, n = await this.loadRaw(e.offset, e.offset + o);
890
- let r = n.slice(0, e.length);
891
- for (const c of s) {
892
- const u = c.insertOffset - e.offset, l = e.length + c.offset, a = n.slice(l, l + c.length);
893
- r = Y(
894
- r.slice(0, u),
895
- a,
896
- r.slice(u)
897
- );
898
- const f = this.#e.get(c.index);
899
- if (f) for (const h of f) {
900
- const g = this.mobi.decode(a.slice(h)), d = K(g);
901
- this.#u(c.index, h, d);
902
- }
903
- }
904
- return this.mobi.decode(r);
905
- }
906
- async createDocument(t) {
907
- const e = await this.loadText(t);
908
- return this.parser.parseFromString(e, this.#c);
909
- }
910
- async loadSection(t) {
911
- if (this.#t.has(t)) return this.#t.get(t);
912
- const e = await this.loadText(t), s = await this.replaceResources(e);
913
- let o = this.parser.parseFromString(s, this.#c);
914
- (o.querySelector("parsererror") || !o.documentElement?.namespaceURI) && (this.#c = E.HTML, o = this.parser.parseFromString(s, this.#c));
915
- for (const [r, c] of this.#l)
916
- for (const u of o.querySelectorAll(`img[src="${r}"]`))
917
- u.replaceWith(c);
918
- const n = URL.createObjectURL(
919
- new Blob([this.serializer.serializeToString(o)], { type: this.#c })
920
- );
921
- return this.#t.set(t, n), n;
922
- }
923
- getIndexByFID(t) {
924
- return this.#r.findIndex((e) => e.frags.some((s) => s.index === t));
925
- }
926
- #u(t, e, s) {
927
- const o = this.#n.get(t);
928
- if (o) o.set(e, s);
929
- else {
930
- const n = /* @__PURE__ */ new Map();
931
- this.#n.set(t, n), n.set(e, s);
932
- }
933
- }
934
- async resolveHref(t) {
935
- const { fid: e, off: s } = q(t), o = this.getIndexByFID(e);
936
- if (o < 0) return;
937
- const n = this.#n.get(e)?.get(s);
938
- if (n) return { index: o, anchor: (d) => d.querySelector(n) };
939
- const { skel: r, frags: c } = this.#r[o], u = c.find((d) => d.index === e), l = r.offset + r.length + u.offset, a = await this.loadRaw(l, l + u.length), f = this.mobi.decode(a.slice(s)), h = K(f);
940
- return this.#u(e, s, h), { index: o, anchor: (d) => d.querySelector(h) };
941
- }
942
- splitTOCHref(t) {
943
- const e = q(t);
944
- return [this.getIndexByFID(e.fid), e];
945
- }
946
- getTOCFragment(t, { fid: e, off: s }) {
947
- const o = this.#n.get(e)?.get(s);
948
- return t.querySelector(o);
949
- }
950
- isExternal(t) {
951
- return /^(?!blob|kindle)\w+:/i.test(t);
952
- }
953
- destroy() {
954
- for (const t of this.#t.values()) URL.revokeObjectURL(t);
955
- }
956
- }
957
- export {
958
- Ct as MOBI,
959
- Bt as isMOBI
960
- };