@prose-reader/streamer 1.303.0 → 1.304.0

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.
package/dist/index.js CHANGED
@@ -1,135 +1,105 @@
1
- import { detectMimeTypeFromName as b, Report as ie, escapeXmlAttributeValue as N, isXmlBasedMimeType as ae, parseContentType as J, isMediaContentMimeType as ce, urlJoin as T } from "@prose-reader/shared";
2
- import { COMIC_INFO_FILENAME as W, parseOpf as de, APPLE_IBOOKS_DISPLAY_OPTIONS_FILENAME as Z, parseAppleDisplayOptionsXml as le, resolveArchiveMetadata as S, parseComicInfo as ue, KOBO_DISPLAY_OPTIONS_FILENAME as z, parseKoboXml as pe, tokenizeXmlSpaceSeparatedList as fe } from "@prose-reader/archive-parser";
3
- import { XmlDocument as R, XmlTextNode as me, XmlElement as he } from "xmldoc";
4
- import { Subject as x, mergeMap as Y, EMPTY as O, pairwise as ge, filter as E, startWith as ye, from as F, tap as k, catchError as C, switchMap as I, merge as M, first as D, takeUntil as be, map as $, ignoreElements as ve, BehaviorSubject as we, distinctUntilChanged as $e, shareReplay as Ae, NEVER as B, timer as Fe, finalize as Ie, of as Te, lastValueFrom as Se } from "rxjs";
5
- const P = (e, t) => {
6
- const o = e.split(/(\d+)/), r = t.split(/(\d+)/);
7
- for (let n = 0, s = o.length; n < s; n++)
8
- if (o[n] !== r[n])
9
- return o[n]?.match(/\d/) ? +(o[n] || "") - +(r[n] || "") : (o[n] || "").localeCompare(r[n] || "");
10
- return 1;
11
- }, A = (e) => e.substring(e.lastIndexOf("/") + 1) || e, j = (e) => e.endsWith("/") ? e.slice(0, -1) : e, Re = (e) => {
12
- const t = e.lastIndexOf("/");
13
- return t >= 0 ? e.substring(0, t) : "";
14
- }, Dt = async (e, {
15
- orderByAlpha: t,
16
- name: o,
17
- encodingFormat: r
18
- } = {}) => {
19
- let n = e;
20
- return t && (n = n.slice().sort((s, i) => P(s.name, i.name))), {
21
- filename: o || "",
22
- encodingFormat: r,
23
- records: n.map((s) => {
24
- const i = s.size, a = A(s.name);
25
- return s.isDir ? {
26
- dir: !0,
27
- basename: a,
28
- uri: s.name,
29
- size: i
30
- } : {
31
- dir: s.isDir,
32
- basename: a,
33
- encodingFormat: b(s.name),
34
- uri: s.name,
35
- blob: async () => new Blob([await s.data()], {
36
- type: b(s.name) ?? ""
37
- }),
38
- string: async () => {
39
- const c = await s.data();
40
- return String.fromCharCode.apply(
41
- null,
42
- Array.from(new Uint16Array(c))
43
- );
44
- },
45
- size: i
46
- };
47
- }),
48
- close: () => Promise.resolve()
49
- };
50
- }, Le = "@prose-reader/streamer", f = ie.namespace(Le, !1, {
51
- color: "#ffae42"
52
- }), xe = (e) => {
53
- const t = {};
54
- for (const r of e) {
55
- const n = r.split("/");
56
- let s = t;
57
- for (let i = 0; i < n.length; i++) {
58
- const a = n[i];
59
- a !== void 0 && (s[a] || (s[a] = {}), s = s[a]);
60
- }
61
- }
62
- const o = (r, n = "") => Object.keys(r).sort().map((s, i, a) => {
63
- const c = i === a.length - 1, d = n + (c ? "└── " : "├── "), u = n + (c ? " " : "│ "), p = r[s];
64
- return p && Object.keys(p).length > 0 ? `${d}${s}/
65
- ${o(p, u)}` : `${d}${s}`;
66
- }).join(`
67
- `);
68
- return o(t);
69
- }, Bt = async (e, {
70
- orderByAlpha: t,
71
- name: o,
72
- encodingFormat: r
73
- } = {}) => {
74
- let n = Object.values(e.files);
75
- t && (n = n.slice().sort((i, a) => P(i.name, a.name)));
76
- const s = {
77
- filename: o || "",
78
- encodingFormat: r,
79
- records: n.map((i) => {
80
- const a = i._data.uncompressedSize, c = A(i.name);
81
- return i.dir ? {
82
- dir: !0,
83
- basename: c,
84
- uri: i.name,
85
- size: a
86
- } : {
87
- dir: !1,
88
- basename: A(i.name),
89
- uri: i.name,
90
- encodingFormat: b(i.name),
91
- blob: () => i.async("blob"),
92
- string: () => i.async("string"),
93
- ...i.internalStream && {
94
- stream: i.internalStream
95
- },
96
- // this is private API
97
- // @ts-expect-error
98
- size: i._data.uncompressedSize
99
- };
100
- }),
101
- close: () => Promise.resolve()
102
- };
103
- if (f.log("Generated archive", s), process.env.NODE_ENV === "development" && f.isEnabled()) {
104
- const i = xe(n.map((a) => a.name));
105
- f.groupCollapsed(...f.getGroupArgs("Archive folder structure")), f.log(`
106
- ${i}`), f.groupEnd();
107
- }
108
- return s;
109
- }, jt = async (e, {
110
- name: t,
111
- encodingFormat: o
112
- } = {}) => {
113
- const r = await e.getFilesArray(), n = {
114
- close: () => e.close(),
115
- filename: t ?? "",
116
- encodingFormat: o,
117
- records: r.map((s) => ({
118
- dir: !1,
119
- basename: s.file.name,
120
- encodingFormat: b(s.file.name),
121
- size: s.file.size,
122
- uri: `${s.path}${s.file.name}`,
123
- blob: async () => await s.file.extract(),
124
- string: async () => (await s.file.extract()).text()
125
- }))
126
- };
127
- return f.log("Generated archive", n), n;
128
- }, Ut = async (e, {
129
- mimeType: t,
130
- direction: o
131
- } = { mimeType: "text/plain" }) => {
132
- const r = `
1
+ import { Report as e, detectMimeTypeFromName as t, escapeXmlAttributeValue as n, isMediaContentMimeType as r, isXmlBasedMimeType as i, parseContentType as a, urlJoin as o } from "@prose-reader/shared";
2
+ import { APPLE_IBOOKS_DISPLAY_OPTIONS_FILENAME as s, COMIC_INFO_FILENAME as c, KOBO_DISPLAY_OPTIONS_FILENAME as l, parseAppleDisplayOptionsXml as u, parseComicInfo as d, parseKoboXml as f, parseOpf as p, resolveArchiveMetadata as m, tokenizeXmlSpaceSeparatedList as ee } from "@prose-reader/archive-parser";
3
+ import { XmlDocument as h, XmlElement as te, XmlTextNode as ne } from "xmldoc";
4
+ import { BehaviorSubject as re, EMPTY as g, NEVER as _, Subject as v, catchError as y, distinctUntilChanged as ie, filter as b, finalize as ae, first as x, from as S, ignoreElements as oe, lastValueFrom as se, map as C, merge as w, mergeMap as T, of as ce, pairwise as le, shareReplay as ue, startWith as de, switchMap as E, takeUntil as fe, tap as D, timer as pe } from "rxjs";
5
+ //#region src/utils/sortByTitleComparator.ts
6
+ var O = (e, t) => {
7
+ let n = e.split(/(\d+)/), r = t.split(/(\d+)/);
8
+ for (let e = 0, t = n.length; e < t; e++) if (n[e] !== r[e]) return n[e]?.match(/\d/) ? (n[e] || "") - +(r[e] || "") : (n[e] || "").localeCompare(r[e] || "");
9
+ return 1;
10
+ }, k = (e) => e.substring(e.lastIndexOf("/") + 1) || e, A = (e) => e.endsWith("/") ? e.slice(0, -1) : e, j = (e) => {
11
+ let t = e.lastIndexOf("/");
12
+ return t >= 0 ? e.substring(0, t) : "";
13
+ }, me = async (e, { orderByAlpha: n, name: r, encodingFormat: i } = {}) => {
14
+ let a = e;
15
+ return n && (a = a.slice().sort((e, t) => O(e.name, t.name))), {
16
+ filename: r || "",
17
+ encodingFormat: i,
18
+ records: a.map((e) => {
19
+ let n = e.size, r = k(e.name);
20
+ return e.isDir ? {
21
+ dir: !0,
22
+ basename: r,
23
+ uri: e.name,
24
+ size: n
25
+ } : {
26
+ dir: e.isDir,
27
+ basename: r,
28
+ encodingFormat: t(e.name),
29
+ uri: e.name,
30
+ blob: async () => new Blob([await e.data()], { type: t(e.name) ?? "" }),
31
+ string: async () => {
32
+ let t = await e.data();
33
+ return String.fromCharCode.apply(null, Array.from(new Uint16Array(t)));
34
+ },
35
+ size: n
36
+ };
37
+ }),
38
+ close: () => Promise.resolve()
39
+ };
40
+ }, M = e.namespace("@prose-reader/streamer", !1, { color: "#ffae42" }), he = (e) => {
41
+ let t = {};
42
+ for (let n of e) {
43
+ let e = n.split("/"), r = t;
44
+ for (let t = 0; t < e.length; t++) {
45
+ let n = e[t];
46
+ n !== void 0 && (r[n] || (r[n] = {}), r = r[n]);
47
+ }
48
+ }
49
+ let n = (e, t = "") => Object.keys(e).sort().map((r, i, a) => {
50
+ let o = i === a.length - 1, s = t + (o ? "└── " : "├── "), c = t + (o ? " " : "│ "), l = e[r];
51
+ return l && Object.keys(l).length > 0 ? `${s}${r}/\n${n(l, c)}` : `${s}${r}`;
52
+ }).join("\n");
53
+ return n(t);
54
+ }, ge = async (e, { orderByAlpha: n, name: r, encodingFormat: i } = {}) => {
55
+ let a = Object.values(e.files);
56
+ n && (a = a.slice().sort((e, t) => O(e.name, t.name)));
57
+ let o = {
58
+ filename: r || "",
59
+ encodingFormat: i,
60
+ records: a.map((e) => {
61
+ let n = e._data.uncompressedSize, r = k(e.name);
62
+ return e.dir ? {
63
+ dir: !0,
64
+ basename: r,
65
+ uri: e.name,
66
+ size: n
67
+ } : {
68
+ dir: !1,
69
+ basename: k(e.name),
70
+ uri: e.name,
71
+ encodingFormat: t(e.name),
72
+ blob: () => e.async("blob"),
73
+ string: () => e.async("string"),
74
+ ...e.internalStream && { stream: e.internalStream },
75
+ size: e._data.uncompressedSize
76
+ };
77
+ }),
78
+ close: () => Promise.resolve()
79
+ };
80
+ if (M.log("Generated archive", o), process.env.NODE_ENV === "development" && M.isEnabled()) {
81
+ let e = he(a.map((e) => e.name));
82
+ M.groupCollapsed(...M.getGroupArgs("Archive folder structure")), M.log(`\n${e}`), M.groupEnd();
83
+ }
84
+ return o;
85
+ }, _e = async (e, { name: n, encodingFormat: r } = {}) => {
86
+ let i = await e.getFilesArray(), a = {
87
+ close: () => e.close(),
88
+ filename: n ?? "",
89
+ encodingFormat: r,
90
+ records: i.map((e) => ({
91
+ dir: !1,
92
+ basename: e.file.name,
93
+ encodingFormat: t(e.file.name),
94
+ size: e.file.size,
95
+ uri: `${e.path}${e.file.name}`,
96
+ blob: async () => await e.file.extract(),
97
+ string: async () => (await e.file.extract()).text()
98
+ }))
99
+ };
100
+ return M.log("Generated archive", a), a;
101
+ }, ve = async (e, { mimeType: t, direction: n } = { mimeType: "text/plain" }) => {
102
+ let r = `
133
103
  <?xml version="1.0" encoding="UTF-8"?>
134
104
  <package xmlns="http://www.idpf.org/2007/opf" version="3.0" xml:lang="ja" prefix="rendition: http://www.idpf.org/vocab/rendition/#"
135
105
  unique-identifier="ootuya-id">
@@ -140,1122 +110,790 @@ ${i}`), f.groupEnd();
140
110
  <manifest>
141
111
  <item id="p01" href="p01.txt" media-type="text/plain"/>
142
112
  </manifest>
143
- <spine page-progression-direction="${o ?? "ltr"}">
113
+ <spine page-progression-direction="${n ?? "ltr"}">
144
114
  <itemref idref="p01" />
145
115
  </spine>
146
116
  </package>
147
117
  `;
148
- return {
149
- filename: "content.txt",
150
- encodingFormat: t,
151
- records: [
152
- {
153
- dir: !1,
154
- basename: A("generated.opf"),
155
- uri: "generated.opf",
156
- blob: async () => new Blob([r]),
157
- string: async () => r,
158
- size: 0
159
- },
160
- {
161
- dir: !1,
162
- basename: A("p01.txt"),
163
- uri: "p01.txt",
164
- blob: async () => typeof e == "string" ? new Blob([e]) : e,
165
- string: async () => typeof e == "string" ? e : e.text(),
166
- size: typeof e == "string" ? e.length : e.size,
167
- encodingFormat: t
168
- }
169
- ],
170
- close: () => Promise.resolve()
171
- };
172
- }, Ee = /^[A-Za-z0-9_][A-Za-z0-9_.-]*$/, ke = /^[A-Za-z0-9_]/, U = /^xml/i, Ce = /[^A-Za-z0-9_.-]+/g, H = "_", We = (e) => e.replace(/^_+|_+$/g, ""), Pe = (e) => We(
173
- e.trim().replaceAll("/", "_").replace(Ce, "_")
174
- ), _e = (e) => {
175
- if (Ee.test(e) && !U.test(e))
176
- return e;
177
- const t = Pe(e), o = t && !U.test(t) ? t : `${H}${t}`;
178
- return ke.test(o) ? o : `${H}${o}`;
179
- }, Ne = (e, t) => {
180
- const o = _e(e);
181
- if (!t.has(o))
182
- return t.add(o), o;
183
- let r = 2, n = `${o}-${r}`;
184
- for (; t.has(n); )
185
- r += 1, n = `${o}-${r}`;
186
- return t.add(n), n;
187
- }, Q = () => {
188
- const e = /* @__PURE__ */ new Set();
189
- return (t) => Ne(t, e);
190
- }, Ht = async (e, t) => {
191
- const o = Q(), r = e.map((a) => ({
192
- id: o(a),
193
- url: a
194
- })), n = `
118
+ return {
119
+ filename: "content.txt",
120
+ encodingFormat: t,
121
+ records: [{
122
+ dir: !1,
123
+ basename: k("generated.opf"),
124
+ uri: "generated.opf",
125
+ blob: async () => new Blob([r]),
126
+ string: async () => r,
127
+ size: 0
128
+ }, {
129
+ dir: !1,
130
+ basename: k("p01.txt"),
131
+ uri: "p01.txt",
132
+ blob: async () => typeof e == "string" ? new Blob([e]) : e,
133
+ string: async () => typeof e == "string" ? e : e.text(),
134
+ size: typeof e == "string" ? e.length : e.size,
135
+ encodingFormat: t
136
+ }],
137
+ close: () => Promise.resolve()
138
+ };
139
+ }, ye = /^[A-Za-z0-9_][A-Za-z0-9_.-]*$/, be = /^[A-Za-z0-9_]/, N = /^xml/i, xe = /[^A-Za-z0-9_.-]+/g, P = "_", Se = (e) => e.replace(/^_+|_+$/g, ""), Ce = (e) => Se(e.trim().replaceAll("/", "_").replace(xe, "_")), F = (e) => {
140
+ if (ye.test(e) && !N.test(e)) return e;
141
+ let t = Ce(e), n = t && !N.test(t) ? t : `${P}${t}`;
142
+ return be.test(n) ? n : `${P}${n}`;
143
+ }, I = (e, t) => {
144
+ let n = F(e);
145
+ if (!t.has(n)) return t.add(n), n;
146
+ let r = 2, i = `${n}-${r}`;
147
+ for (; t.has(i);) r += 1, i = `${n}-${r}`;
148
+ return t.add(i), i;
149
+ }, L = () => {
150
+ let e = /* @__PURE__ */ new Set();
151
+ return (t) => I(t, e);
152
+ }, we = async (e, r) => {
153
+ let i = L(), a = e.map((e) => ({
154
+ id: i(e),
155
+ url: e
156
+ })), o = `
195
157
  <?xml version="1.0" encoding="UTF-8"?><package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="bookid">
196
158
  <metadata>
197
- <meta property="rendition:layout">${t?.useRenditionFlow ? "reflowable" : "pre-paginated"}</meta>
198
- ${t?.useRenditionFlow ? '<meta property="rendition:flow">scrolled-continuous</meta>' : ""}
159
+ <meta property="rendition:layout">${r?.useRenditionFlow ? "reflowable" : "pre-paginated"}</meta>
160
+ ${r?.useRenditionFlow ? "<meta property=\"rendition:flow\">scrolled-continuous</meta>" : ""}
199
161
  </metadata>
200
162
  <manifest>
201
- ${r.map(({ id: a, url: c }) => {
202
- const d = b(c);
203
- return `<item id="${a}" href="${N(c)}" media-type="${N(d ?? "")}"/>`;
204
- }).join(`
205
- `)}
163
+ ${a.map(({ id: e, url: r }) => {
164
+ let i = t(r);
165
+ return `<item id="${e}" href="${n(r)}" media-type="${n(i ?? "")}"/>`;
166
+ }).join("\n")}
206
167
  </manifest>
207
168
  <spine>
208
- ${r.map(({ id: a }) => `<itemref idref="${a}" />`).join(`
209
- `)}
169
+ ${a.map(({ id: e }) => `<itemref idref="${e}" />`).join("\n")}
210
170
  </spine>
211
171
  </package>
212
- `, s = e.map((a) => ({
213
- dir: !1,
214
- basename: A(a),
215
- encodingFormat: b(a),
216
- uri: a,
217
- size: 100 / e.length,
218
- blob: async () => (await fetch(a)).blob(),
219
- string: async () => ""
220
- }));
221
- return {
222
- filename: "",
223
- records: [{
224
- dir: !1,
225
- basename: "content.opf",
226
- uri: "content.opf",
227
- size: 0,
228
- blob: async () => new Blob(),
229
- string: async () => n
230
- }, ...s],
231
- close: () => Promise.resolve()
232
- };
233
- }, ze = (e) => !e.dir, Oe = W.toLowerCase(), Me = (e) => e.records.find(
234
- (t) => ze(t) && t.basename.toLowerCase() === Oe
235
- ), Xt = ({
236
- enableReport: e
237
- } = {}) => {
238
- f.enable(!!e);
239
- }, _ = (e) => {
240
- const o = Object.values(e.records).filter(
241
- (r) => !r.dir
242
- ).find((r) => r.uri.endsWith(".opf"));
243
- return {
244
- data: o,
245
- basePath: o?.uri.substring(0, o.uri.lastIndexOf("/")) || ""
246
- };
172
+ `;
173
+ return {
174
+ filename: "",
175
+ records: [{
176
+ dir: !1,
177
+ basename: "content.opf",
178
+ uri: "content.opf",
179
+ size: 0,
180
+ blob: async () => new Blob(),
181
+ string: async () => o
182
+ }, ...e.map((n) => ({
183
+ dir: !1,
184
+ basename: k(n),
185
+ encodingFormat: t(n),
186
+ uri: n,
187
+ size: 100 / e.length,
188
+ blob: async () => (await fetch(n)).blob(),
189
+ string: async () => ""
190
+ }))],
191
+ close: () => Promise.resolve()
192
+ };
193
+ }, Te = (e) => !e.dir, Ee = c.toLowerCase(), R = (e) => e.records.find((e) => Te(e) && e.basename.toLowerCase() === Ee), De = ({ enableReport: e } = {}) => {
194
+ M.enable(!!e);
195
+ }, z = (e) => {
196
+ let t = Object.values(e.records).filter((e) => !e.dir).find((e) => e.uri.endsWith(".opf"));
197
+ return {
198
+ data: t,
199
+ basePath: t?.uri.substring(0, t.uri.lastIndexOf("/")) || ""
200
+ };
247
201
  };
248
- async function ee(e) {
249
- const { data: t, basePath: o } = _(e) || {};
250
- if (!t || t.dir)
251
- return;
252
- const r = await t.string();
253
- return {
254
- opf: de(r),
255
- basePath: o
256
- };
202
+ //#endregion
203
+ //#region src/epubs/readArchiveOpf.ts
204
+ async function B(e) {
205
+ let { data: t, basePath: n } = z(e) || {};
206
+ if (!(!t || t.dir)) return {
207
+ opf: p(await t.string()),
208
+ basePath: n
209
+ };
257
210
  }
258
- const De = Z.toLowerCase(), Be = ({ archive: e }) => async (t) => {
259
- const o = e.records.find(
260
- (n) => !n.dir && n.basename.toLowerCase() === De
261
- );
262
- if (!o || o.dir)
263
- return t;
264
- const r = await o.string();
265
- try {
266
- const n = le(r), { renditionLayout: s } = S(n);
267
- return {
268
- ...t,
269
- renditionLayout: t.renditionLayout ?? s
270
- };
271
- } catch (n) {
272
- return console.error(
273
- `Unable to parse ${Z} for content
274
- `,
275
- r
276
- ), console.error(n), t;
277
- }
278
- }, je = W.toLowerCase(), Ue = ({ archive: e }) => async (t) => {
279
- const o = Me(e);
280
- if (!o)
281
- return t;
282
- const r = {
283
- ...t,
284
- spineItems: t.spineItems.filter(
285
- (s) => !s.id.toLowerCase().endsWith(je)
286
- ).map((s, i, a) => ({
287
- ...s,
288
- progressionWeight: 1 / a.length
289
- }))
290
- }, n = await o.string();
291
- try {
292
- const s = ue(n), i = S(s);
293
- return {
294
- ...r,
295
- readingDirection: i.readingDirection ?? r.readingDirection
296
- };
297
- } catch (s) {
298
- return console.error(
299
- `Unable to parse ${W} for content
300
- `,
301
- n
302
- ), console.error(s), r;
303
- }
304
- }, He = ({
305
- baseUrl: e = "",
306
- resourcePath: t
307
- }) => {
308
- if (!e && /^https?:\/\//.test(t))
309
- return encodeURI(t);
310
- const o = e ? `${e}${e.endsWith("/") ? "" : "/"}` : "file://";
311
- return encodeURI(`${o}${t}`);
312
- }, Xe = ({ archive: e, baseUrl: t }) => async () => {
313
- const o = Object.values(e.records).filter((s) => !s.dir), r = Q(), n = o.map((s) => ({
314
- file: s,
315
- id: r(s.uri)
316
- }));
317
- return {
318
- filename: e.filename,
319
- title: e.records.find(({ dir: s }) => s)?.basename.replace(/\/$/, "") || e.filename,
320
- renditionLayout: void 0,
321
- renditionSpread: "auto",
322
- readingDirection: void 0,
323
- spineItems: n.filter(({ file: s }) => !s.basename.endsWith(".db")).map(({ file: s, id: i }, a) => ({
324
- id: i,
325
- index: a,
326
- href: He({
327
- baseUrl: t,
328
- resourcePath: s.uri
329
- }),
330
- renditionLayout: void 0,
331
- progressionWeight: 1 / o.length,
332
- pageSpreadLeft: void 0,
333
- pageSpreadRight: void 0,
334
- mediaType: s.encodingFormat
335
- })),
336
- items: n.map(({ file: s, id: i }) => ({
337
- id: i,
338
- href: encodeURI(`${t}${s.uri}`)
339
- }))
340
- };
341
- }, te = async ({
342
- archive: e,
343
- archiveOpf: t
344
- }) => {
345
- if (!t) return [];
346
- const { opf: o, basePath: r } = t, { spineRows: n } = o;
347
- return e.records.filter((i) => n.find((a) => r ? `${r}/${a.href}` === i.uri : `${a.href}` === i.uri));
348
- }, ne = (e, t, o) => {
349
- const { basePath: r } = _(t) || {};
350
- return e.map((n) => {
351
- const s = n.href, i = o?.(s) ?? "";
352
- return {
353
- href: r ? `${i}${r}/${s}` : `${i}${s}`,
354
- id: n.id,
355
- mediaType: n.mediaType
356
- };
357
- });
358
- }, Ve = (e) => {
359
- const t = e?.trim();
360
- return t === "scrolled-continuous" || t === "scrolled-doc" || t === "paginated" || t === "auto" ? t : "auto";
361
- }, Ge = (e) => {
362
- const t = e?.trim();
363
- if (t === "none" || t === "landscape" || t === "portrait" || t === "both" || t === "auto")
364
- return t;
365
- }, Ke = (e) => {
366
- const t = e?.trim();
367
- if (t === "cover" || t === "title-page" || t === "copyright-page" || t === "text")
368
- return t;
369
- }, qe = ({
370
- archive: e,
371
- baseUrl: t,
372
- archiveOpf: o
373
- }) => async (r) => {
374
- if (!o)
375
- return r;
376
- const { opf: n, basePath: s } = o, i = S(n);
377
- f.groupCollapsed(...f.getGroupArgs("OPF parsed")), f.log("opf", n), f.groupEnd();
378
- const a = n.renditionLayoutMeta?.trim(), c = a === "reflowable" || a === "pre-paginated" ? a : i.renditionLayout, d = n.title?.trim() || e.records.find(({ dir: l }) => l)?.basename || "", u = i.readingDirection ?? r.readingDirection, m = (await te({
379
- archive: e,
380
- archiveOpf: o
381
- })).reduce(
382
- (l, v) => v.size + l,
383
- 0
384
- ), h = n.guide, y = [];
385
- for (const l of h) {
386
- const v = Ke(l.type);
387
- v !== void 0 && y.push({ href: l.href, title: l.title, type: v });
388
- }
389
- return {
390
- filename: e.filename,
391
- renditionLayout: c,
392
- renditionFlow: Ve(n.renditionFlowMeta),
393
- renditionSpread: Ge(n.renditionSpreadMeta),
394
- title: d,
395
- readingDirection: u,
396
- /**
397
- * @see https://www.w3.org/TR/epub/#sec-itemref-elem
398
- */
399
- spineItems: n.spineRows.map((l, v) => {
400
- const g = e.records.find((L) => L.uri.endsWith(l.href))?.size || 0, w = t || (/^https?:\/\//.test(l.href) ? "" : "file://");
401
- return {
402
- id: l.id,
403
- index: v,
404
- href: l.href.startsWith("https://") ? l.href : s ? `${w}${s}/${l.href}` : `${w}${l.href}`,
405
- renditionLayout: l.renditionLayout ?? c,
406
- ...l.renditionFlow !== void 0 ? { renditionFlow: l.renditionFlow } : {},
407
- progressionWeight: g / m,
408
- pageSpreadLeft: l.pageSpreadLeft,
409
- pageSpreadRight: l.pageSpreadRight,
410
- mediaType: l.mediaType
411
- };
412
- }),
413
- items: ne(n.manifestItems, e, (l) => /^https?:\/\//.test(l) ? "" : t || "file://"),
414
- guide: y.length > 0 ? y : void 0
415
- };
416
- }, Je = (e) => {
417
- const t = e.descendantWithPath("head")?.childrenNamed("meta").find((o) => o.attr.name === "viewport");
418
- return !!(t && t.attr.name === "viewport");
419
- }, Ze = (e) => e.reduce(async (t, o) => {
420
- if (!await t || !ae({
421
- mimeType: o.encodingFormat,
422
- uri: o.uri
423
- }))
424
- return !1;
425
- const n = o.dir ? null : await o.string();
426
- return n ? Je(new R(n)) : !1;
427
- }, Promise.resolve(!0)), Ye = ({
428
- archive: e,
429
- archiveOpf: t
430
- }) => async (o) => {
431
- if (o.renditionLayout === "reflowable" && o.spineItems.every((n) => n.renditionLayout === "reflowable")) {
432
- const n = await te({
433
- archive: e,
434
- archiveOpf: t
435
- });
436
- if (await Ze(n))
437
- return {
438
- ...o,
439
- spineItems: o.spineItems.map((i) => ({
440
- ...i,
441
- renditionLayout: "pre-paginated"
442
- })),
443
- renditionLayout: "pre-paginated"
444
- };
445
- }
446
- return o;
447
- }, Qe = () => (e) => ({
448
- ...e,
449
- readingDirection: e.readingDirection ?? "ltr"
450
- }), et = async (e) => {
451
- let t;
452
- return await Promise.all(
453
- e.records.map(async (o) => {
454
- if (o.dir || !o.uri.endsWith(z)) return;
455
- const r = await o.string();
456
- try {
457
- const { renditionLayout: n } = pe(r);
458
- n && (t = n);
459
- } catch (n) {
460
- console.error(
461
- `Unable to parse ${z} for content
462
- `,
463
- r
464
- ), console.error(n);
465
- }
466
- })
467
- ), {
468
- kind: "kobo",
469
- ...t !== void 0 ? { renditionLayout: t } : {}
470
- };
471
- }, tt = ({ archive: e }) => async (t) => {
472
- const o = await et(e), { renditionLayout: r } = S(o);
473
- return {
474
- ...t,
475
- renditionLayout: t.renditionLayout ?? r
476
- };
477
- }, X = (e) => e.toLowerCase().endsWith(".opf"), nt = (e) => e.records.some(
478
- (t) => !t.dir && (X(t.basename) || X(t.uri))
479
- ), rt = ({ archive: e }) => async (t) => nt(e) ? t : {
480
- ...t,
481
- spineItems: t.spineItems.map((r) => {
482
- const n = e.records.find(
483
- (i) => decodeURI(r.href).endsWith(i.uri)
484
- ), s = J(n?.encodingFormat ?? "") || b(n?.basename ?? "");
485
- return {
486
- ...r,
487
- renditionLayout: s && ce(s) ? "pre-paginated" : r.renditionLayout
488
- };
489
- })
490
- }, re = (e) => e ? e.children.map((t) => t instanceof me ? t.text : t instanceof he ? re(t) : "").join("").trim() : "", st = (e) => fe(e.properties).includes("nav"), se = (e, { basePath: t, baseUrl: o }) => {
491
- const r = {
492
- contents: [],
493
- path: "",
494
- href: "",
495
- title: ""
496
- };
497
- let n = e.childNamed("span") || e.childNamed("a");
498
- r.title = (n?.attr.title || n?.val.trim() || re(n)) ?? "";
499
- let s = n?.name;
500
- s !== "a" && (n = e.descendantWithPath(`${s}.a`), n && (s = n.name.toLowerCase())), s === "a" && n?.attr.href && (r.path = T(t, n.attr.href), r.href = T(o, t, n.attr.href));
501
- const i = e.childNamed("ol");
502
- if (i) {
503
- const a = i.childrenNamed("li");
504
- a && a.length > 0 && (r.contents = a.map(
505
- (c) => se(c, { basePath: t, baseUrl: o })
506
- ));
507
- }
508
- return r;
509
- }, ot = (e, { basePath: t, baseUrl: o }) => {
510
- const r = [];
511
- let n;
512
- return e.descendantWithPath("body.nav.ol") ? n = e.descendantWithPath("body.nav.ol")?.children : e.descendantWithPath("body.section.nav.ol") && (n = e.descendantWithPath("body.section.nav.ol")?.children), n && n.length > 0 && n.filter((s) => s.name === "li").forEach((s) => {
513
- r.push(se(s, { basePath: t, baseUrl: o }));
514
- }), r;
515
- }, it = async (e, t, { baseUrl: o }) => {
516
- const r = e.manifestItems.find(st);
517
- if (r?.href) {
518
- const n = Object.values(t.records).find(
519
- (s) => s.uri.endsWith(r.href)
520
- );
521
- if (n && !n.dir) {
522
- const s = new R(await n.string()), i = Re(n.uri);
523
- return ot(s, { basePath: i, baseUrl: o });
524
- }
525
- }
526
- }, oe = (e, {
527
- opfBasePath: t,
528
- baseUrl: o,
529
- prefix: r
530
- }) => {
531
- const n = e?.childNamed(`${r}content`)?.attr.src || "", s = {
532
- title: e?.descendantWithPath(`${r}navLabel.${r}text`)?.val || "",
533
- path: T(t, n),
534
- href: T(o, t, n),
535
- contents: []
536
- }, i = e.childrenNamed(`${r}navPoint`);
537
- return i && i.length > 0 && (s.contents = i.map(
538
- (a) => oe(a, { opfBasePath: t, baseUrl: o, prefix: r })
539
- )), s;
540
- }, at = (e, { opfBasePath: t, baseUrl: o }) => {
541
- const r = [], n = e.name;
542
- let s = "";
543
- return n.indexOf(":") !== -1 && (s = `${n.split(":")[0]}:`), e.childNamed(`${s}navMap`)?.childrenNamed(`${s}navPoint`).forEach((i) => {
544
- r.push(oe(i, { opfBasePath: t, baseUrl: o, prefix: s }));
545
- }), r;
546
- }, ct = async ({
547
- opf: e,
548
- opfBasePath: t,
549
- baseUrl: o,
550
- archive: r
551
- }) => {
552
- const n = e.spineTocIdref;
553
- if (n) {
554
- const s = e.manifestItems.find((i) => i.id === n);
555
- if (s) {
556
- const i = `${t}${t === "" ? "" : "/"}${s.href}`, a = Object.values(r.records).find(
557
- (c) => c.uri.endsWith(i)
558
- );
559
- if (a && !a.dir) {
560
- const c = new R(await a.string());
561
- return at(c, { opfBasePath: t, baseUrl: o });
562
- }
563
- }
564
- }
565
- }, dt = async (e, t, { baseUrl: o }) => {
566
- const { basePath: r } = _(t) || {}, n = await it(e, t, {
567
- baseUrl: o
568
- });
569
- if (n)
570
- return n;
571
- const s = await ct({
572
- opf: e,
573
- opfBasePath: r ?? "",
574
- archive: t,
575
- baseUrl: o
576
- });
577
- if (s)
578
- return s;
579
- }, lt = (e) => e.replace(/\.[^.]+$/, "").replace(/[_-]/g, " ").replace(/\s+/g, " ").trim(), ut = (e, t) => {
580
- if (!(e.spineItems.length === 0 || !e.spineItems.every((r) => (J(r.mediaType ?? "") || b(r.href))?.startsWith("audio/"))))
581
- return e.spineItems.map((r) => {
582
- const n = t.records.find(
583
- (s) => !s.dir && decodeURI(r.href).endsWith(s.uri)
584
- );
585
- return {
586
- title: lt(n?.basename ?? r.href),
587
- href: r.href,
588
- path: n?.uri ?? r.href,
589
- contents: []
590
- };
591
- });
592
- }, pt = (e, { baseUrl: t }) => {
593
- const o = [...e.records].sort(
594
- (n, s) => P(n.uri, s.uri)
595
- ), r = (n, s, i, a, c) => {
596
- const d = n.find((m) => m.title === s), [u, ...p] = i;
597
- return d ? u ? [
598
- ...n.filter((h) => h !== d),
599
- {
600
- ...d,
601
- contents: [
602
- ...d.contents,
603
- ...r(
604
- d.contents,
605
- u,
606
- p,
607
- a,
608
- c
609
- )
610
- ]
611
- }
612
- ] : d.path.split("/").length > c.split("/").length ? [
613
- ...n.filter((h) => h !== d),
614
- {
615
- ...d,
616
- path: c,
617
- href: a
618
- }
619
- ] : n : u ? [
620
- ...n,
621
- {
622
- contents: r(
623
- [],
624
- u,
625
- p,
626
- a,
627
- c
628
- ),
629
- href: a,
630
- path: c,
631
- title: s
632
- }
633
- ] : [
634
- ...n,
635
- {
636
- contents: [],
637
- href: a,
638
- path: c,
639
- title: s
640
- }
641
- ];
642
- };
643
- return o.reduce((n, s) => {
644
- if (s.dir) return n;
645
- const i = s.uri.split("/").slice(0, -1), [a, ...c] = i;
646
- if (!a) return n;
647
- const d = T(t, encodeURI(s.uri)).replace(/\/$/, ""), u = s.uri.replace(/\/$/, "");
648
- return r(n, a, c, d, u);
649
- }, []);
650
- }, ft = async (e, t, {
651
- baseUrl: o,
652
- archiveOpf: r
653
- }) => {
654
- if (r)
655
- return await dt(r.opf, e, { baseUrl: o }) || [];
656
- const n = ut(t, e);
657
- if (n) return n;
658
- const s = pt(e, { baseUrl: o });
659
- if (s.length !== 0)
660
- return s;
661
- }, mt = ({
662
- archive: e,
663
- baseUrl: t,
664
- archiveOpf: o
665
- }) => async (r) => {
666
- if (r.nav) return r;
667
- const n = await ft(e, r, {
668
- baseUrl: t,
669
- archiveOpf: o
670
- });
671
- return n ? {
672
- ...r,
673
- nav: {
674
- toc: n
675
- }
676
- } : r;
677
- }, ht = (e) => e ? e.endsWith("/") ? e : `${e}/` : "", gt = async (e, {
678
- baseUrl: t = "",
679
- hooks: o = {}
680
- } = {}) => {
681
- f.log("Generating manifest from archive", e);
682
- const r = await ee(e), n = ht(t), s = (p) => (p ?? []).map(
683
- (m) => m({ archive: e, baseUrl: n })
684
- ), i = [
685
- qe({ archive: e, baseUrl: n, archiveOpf: r }),
686
- Ue({ archive: e }),
687
- Be({ archive: e }),
688
- rt({ archive: e }),
689
- ...s(o.content)
690
- ], a = s(o.spine), c = [
691
- Ye({ archive: e, archiveOpf: r }),
692
- tt({ archive: e }),
693
- ...s(o.presentation)
694
- ], d = [
695
- mt({ archive: e, baseUrl: n, archiveOpf: r }),
696
- ...s(o.navigation)
697
- ], u = [
698
- ...i,
699
- ...a,
700
- ...c,
701
- ...d,
702
- Qe()
703
- ];
704
- try {
705
- const p = Xe({
706
- archive: e,
707
- baseUrl: n
708
- })(), m = await u.reduce(async (h, y) => await y(await h), p);
709
- if (f.log("Generated manifest", m), process.env.NODE_ENV === "development" && f.isEnabled()) {
710
- const h = JSON.stringify(m, null, 2);
711
- f.groupCollapsed(...f.getGroupArgs("Generated manifest")), f.log(`
712
- ${h}`), f.groupEnd();
713
- }
714
- return m;
715
- } catch (p) {
716
- throw f.error(p), p;
717
- }
718
- }, yt = (e) => {
719
- const t = e.descendantWithPath("head")?.childrenNamed("meta").find((o) => o.attr.name === "calibre:cover");
720
- return !!(t && t.attr.name === "calibre:cover");
721
- }, bt = (e) => e.descendantWithPath("body")?.descendantWithPath("div")?.childrenNamed("svg")?.find(
722
- (t) => t.attr.width === "100%" && t.attr.preserveAspectRatio === "none"
723
- ), vt = ({ archive: e, resourcePath: t }) => async (o) => {
724
- const r = Object.values(e.records).find(
725
- (n) => n.uri === t && !n.dir
726
- );
727
- if (r && !r.dir && r.basename.endsWith(".xhtml")) {
728
- const n = typeof o.body == "string" ? o.body : await r.string(), s = new R(n);
729
- if (yt(s)) {
730
- const i = bt(s);
731
- return i && delete i.attr.preserveAspectRatio, {
732
- ...o,
733
- body: s?.toString()
734
- };
735
- }
736
- }
737
- return o;
738
- }, wt = ({ archive: e, resourcePath: t }) => async (o) => vt({ archive: e, resourcePath: t })(o), $t = ({ archive: e, resourcePath: t }) => async (o) => {
739
- const r = Object.values(e.records).find(
740
- (n) => n.uri === t && !n.dir
741
- );
742
- if (r && !r.dir && r.basename.endsWith(".css")) {
743
- const s = (typeof o.body == "string" ? o.body : await r.string()).replaceAll(
744
- "-webkit-writing-mode",
745
- "writing-mode"
746
- );
747
- return {
748
- ...o,
749
- body: s
750
- };
751
- }
752
- return o;
753
- }, At = async (e, t) => {
754
- const o = await ee(e);
755
- if (o) {
756
- const { opf: r } = o, n = ne(r.manifestItems, e, () => "");
757
- if (n.find(
758
- (i) => t.endsWith(i.href)
759
- )?.mediaType)
760
- return {
761
- mediaType: n.find((i) => t.endsWith(i.href))?.mediaType
762
- };
763
- }
764
- return {
765
- mediaType: Ft(t)
766
- };
767
- }, Ft = (e) => {
768
- if (e.endsWith(".css"))
769
- return "text/css; charset=UTF-8";
770
- if (e.endsWith(".jpg"))
771
- return "image/jpg";
772
- if (e.endsWith(".xhtml"))
773
- return "application/xhtml+xml";
774
- if (e.endsWith(".mp4"))
775
- return "video/mp4";
776
- if (e.endsWith(".svg"))
777
- return "image/svg+xml";
778
- }, It = ({ archive: e, resourcePath: t }) => async (o) => {
779
- const r = Object.values(e.records).find(
780
- (s) => s.uri === t && !s.dir
781
- );
782
- if (!r || r.dir) return o;
783
- const n = await At(e, t);
784
- return {
785
- ...o,
786
- params: {
787
- ...o.params,
788
- ...r?.encodingFormat && {
789
- contentType: r.encodingFormat
790
- },
791
- ...n.mediaType && {
792
- contentType: n.mediaType
793
- }
794
- }
795
- };
796
- }, V = [
797
- "div",
798
- "span",
799
- "p",
800
- "a",
801
- "li",
802
- "ul",
803
- "ol",
804
- "h1",
805
- "h2",
806
- "h3",
807
- "h4",
808
- "h5",
809
- "h6",
810
- "table",
811
- "tr",
812
- "td",
813
- "th",
814
- "thead",
815
- "tbody",
816
- "tfoot",
817
- "section",
818
- "article",
819
- "header",
820
- "footer",
821
- "nav",
822
- "aside",
823
- "main",
824
- "figure",
825
- "figcaption",
826
- "blockquote",
827
- "pre",
828
- "code",
829
- "form",
830
- "textarea",
831
- "select",
832
- "option",
833
- "button",
834
- "label",
835
- "fieldset",
836
- "legend",
837
- "caption",
838
- "dl",
839
- "dt",
840
- "dd",
841
- "iframe",
842
- "video",
843
- "audio",
844
- "canvas",
845
- "script",
846
- "style"
847
- ], Tt = ({ archive: e, resourcePath: t }) => async (o) => {
848
- const r = Object.values(e.records).find(
849
- (n) => n.uri === t && !n.dir
850
- );
851
- if (r && !r.dir && r.basename.endsWith(".xhtml")) {
852
- const n = typeof o.body == "string" ? o.body : await r.string();
853
- if (!new RegExp(
854
- `<(${V.join("|")})[\\s/>]`,
855
- "i"
856
- ).test(n))
857
- return o;
858
- const i = new RegExp(
859
- `<(${V.join("|")})(\\s[^>]*)?\\s*/>`,
860
- "gi"
861
- ), a = n.replace(
862
- i,
863
- (c, d, u = "") => `<${d} ${u.trim()}></${d}>`
864
- );
865
- return {
866
- ...o,
867
- body: a
868
- };
869
- }
870
- return o;
871
- }, St = async (e, t, { hooks: o = [] } = {}) => {
872
- const r = {
873
- params: {}
874
- }, s = [
875
- ...o.map((i) => i({ archive: e, resourcePath: t })),
876
- It({ archive: e, resourcePath: t }),
877
- Tt({ archive: e, resourcePath: t }),
878
- $t({ archive: e, resourcePath: t }),
879
- wt({ archive: e, resourcePath: t })
880
- ];
881
- try {
882
- const i = await s.reduce(async (c, d) => await d(await c), Promise.resolve(r));
883
- if (f.log("Generated resource", t, i), i.body !== void 0)
884
- return i;
885
- const a = Object.values(e.records).find(
886
- (c) => c.uri === t && !c.dir
887
- );
888
- if (!a || a.dir)
889
- throw new Error(`no file found for resourcePath:${t}`);
890
- return {
891
- ...i,
892
- body: await a.blob()
893
- };
894
- } catch (i) {
895
- throw f.error(i), i;
896
- }
897
- };
898
- class Rt {
899
- constructor(t) {
900
- this.cleanArchiveAfter = t, this.state$ = new we({
901
- status: "idle",
902
- locks: 0
903
- });
904
- }
905
- update(t) {
906
- this.state$.next({ ...this.state$.getValue(), ...t });
907
- }
908
- get locks$() {
909
- return this.state$.pipe($(({ locks: t }) => t));
910
- }
911
- get state() {
912
- return this.state$.getValue();
913
- }
914
- get isUnlocked$() {
915
- return this.locks$.pipe(
916
- $((t) => t <= 0),
917
- $e(),
918
- Ae()
919
- );
920
- }
921
- get overTTL$() {
922
- return this.isUnlocked$.pipe(
923
- I(
924
- (t) => t ? this.cleanArchiveAfter === 1 / 0 ? B : Fe(this.cleanArchiveAfter) : B
925
- )
926
- );
927
- }
928
- }
929
- const Lt = ({
930
- getArchive: e,
931
- cleanArchiveAfter: t = 300 * 1e3
932
- // 5mn
933
- }) => {
934
- const o = new x(), r = new x(), n = new x(), s = {}, i = o.pipe(
935
- Y((d) => {
936
- const u = s[d];
937
- if (!u || u.state.status !== "idle") return O;
938
- let p = !1;
939
- const m = (g) => {
940
- f.debug(`Cleaning up archive with key: ${g}`);
941
- const w = s[g];
942
- delete s[g], p || (w?.state.archive?.close(), p = !0);
943
- };
944
- u.update({
945
- status: "loading"
946
- });
947
- const h = u.locks$, y = u.isUnlocked$, l = h.pipe(
948
- ge(),
949
- E(([g, w]) => w > g),
950
- ye(!0)
951
- );
952
- return F(e(d)).pipe(
953
- k((g) => {
954
- u.update({
955
- archive: g,
956
- status: "success"
957
- });
958
- }),
959
- C((g) => (m(d), u.update({
960
- status: "error",
961
- error: g
962
- }), O)),
963
- I(() => {
964
- const g = l.pipe(
965
- I(() => n),
966
- I(() => y),
967
- E((L) => L)
968
- );
969
- return M(g, u.overTTL$).pipe(
970
- D(),
971
- k(() => {
972
- m(d);
973
- })
974
- );
975
- })
976
- );
977
- }),
978
- be(r)
979
- ), a = (d) => {
980
- let u = !1;
981
- const p = s[d] ?? new Rt(t);
982
- s[d] = p, p.update({
983
- locks: p.state.locks + 1
984
- });
985
- const m = () => {
986
- u || (u = !0, p.update({
987
- locks: p.state.locks - 1
988
- }));
989
- };
990
- o.next(d);
991
- const h = p.state$.pipe(
992
- $(({ archive: l }) => l),
993
- E((l) => !!l)
994
- ), y = p.state$.pipe(
995
- k(({ error: l }) => {
996
- if (l)
997
- throw l;
998
- }),
999
- ve()
1000
- );
1001
- return M(h, y).pipe(
1002
- D(),
1003
- $((l) => ({ archive: l, release: m })),
1004
- C((l) => {
1005
- throw m(), l;
1006
- })
1007
- );
1008
- }, c = () => {
1009
- n.next();
1010
- };
1011
- return i.subscribe(), {
1012
- access: a,
1013
- purge: c,
1014
- _archives: s
1015
- };
1016
- }, G = (e) => e ? /^\d+$/.test(e) ? {
1017
- valid: !0,
1018
- value: Number.parseInt(e, 10)
211
+ //#endregion
212
+ //#region src/generators/manifest/hooks/apple.ts
213
+ var Oe = s.toLowerCase(), ke = ({ archive: e }) => async (t) => {
214
+ let n = e.records.find((e) => !e.dir && e.basename.toLowerCase() === Oe);
215
+ if (!n || n.dir) return t;
216
+ let r = await n.string();
217
+ try {
218
+ let { renditionLayout: e } = m(u(r));
219
+ return {
220
+ ...t,
221
+ renditionLayout: t.renditionLayout ?? e
222
+ };
223
+ } catch (e) {
224
+ return console.error(`Unable to parse ${s} for content\n`, r), console.error(e), t;
225
+ }
226
+ }, Ae = c.toLowerCase(), je = ({ archive: e }) => async (t) => {
227
+ let n = R(e);
228
+ if (!n) return t;
229
+ let r = {
230
+ ...t,
231
+ spineItems: t.spineItems.filter((e) => !e.id.toLowerCase().endsWith(Ae)).map((e, t, n) => ({
232
+ ...e,
233
+ progressionWeight: 1 / n.length
234
+ }))
235
+ }, i = await n.string();
236
+ try {
237
+ let e = m(d(i));
238
+ return {
239
+ ...r,
240
+ readingDirection: e.readingDirection ?? r.readingDirection
241
+ };
242
+ } catch (e) {
243
+ return console.error(`Unable to parse ${c} for content\n`, i), console.error(e), r;
244
+ }
245
+ }, Me = ({ baseUrl: e = "", resourcePath: t }) => {
246
+ if (!e && /^https?:\/\//.test(t)) return encodeURI(t);
247
+ let n = e ? `${e}${e.endsWith("/") ? "" : "/"}` : "file://";
248
+ return encodeURI(`${n}${t}`);
249
+ }, Ne = ({ archive: e, baseUrl: t }) => async () => {
250
+ let n = Object.values(e.records).filter((e) => !e.dir), r = L(), i = n.map((e) => ({
251
+ file: e,
252
+ id: r(e.uri)
253
+ }));
254
+ return {
255
+ filename: e.filename,
256
+ title: e.records.find(({ dir: e }) => e)?.basename.replace(/\/$/, "") || e.filename,
257
+ renditionLayout: void 0,
258
+ renditionSpread: "auto",
259
+ readingDirection: void 0,
260
+ spineItems: i.filter(({ file: e }) => !e.basename.endsWith(".db")).map(({ file: e, id: r }, i) => ({
261
+ id: r,
262
+ index: i,
263
+ href: Me({
264
+ baseUrl: t,
265
+ resourcePath: e.uri
266
+ }),
267
+ renditionLayout: void 0,
268
+ progressionWeight: 1 / n.length,
269
+ pageSpreadLeft: void 0,
270
+ pageSpreadRight: void 0,
271
+ mediaType: e.encodingFormat
272
+ })),
273
+ items: i.map(({ file: e, id: n }) => ({
274
+ id: n,
275
+ href: encodeURI(`${t}${e.uri}`)
276
+ }))
277
+ };
278
+ }, V = async ({ archive: e, archiveOpf: t }) => {
279
+ if (!t) return [];
280
+ let { opf: n, basePath: r } = t, { spineRows: i } = n;
281
+ return e.records.filter((e) => i.find((t) => r ? `${r}/${t.href}` === e.uri : `${t.href}` === e.uri));
282
+ }, H = (e, t, n) => {
283
+ let { basePath: r } = z(t) || {};
284
+ return e.map((e) => {
285
+ let t = e.href, i = n?.(t) ?? "";
286
+ return {
287
+ href: r ? `${i}${r}/${t}` : `${i}${t}`,
288
+ id: e.id,
289
+ mediaType: e.mediaType
290
+ };
291
+ });
292
+ }, Pe = (e) => {
293
+ let t = e?.trim();
294
+ return t === "scrolled-continuous" || t === "scrolled-doc" || t === "paginated" || t === "auto" ? t : "auto";
295
+ }, Fe = (e) => {
296
+ let t = e?.trim();
297
+ if (t === "none" || t === "landscape" || t === "portrait" || t === "both" || t === "auto") return t;
298
+ }, Ie = (e) => {
299
+ let t = e?.trim();
300
+ if (t === "cover" || t === "title-page" || t === "copyright-page" || t === "text") return t;
301
+ }, Le = ({ archive: e, baseUrl: t, archiveOpf: n }) => async (r) => {
302
+ if (!n) return r;
303
+ let { opf: i, basePath: a } = n, o = m(i);
304
+ M.groupCollapsed(...M.getGroupArgs("OPF parsed")), M.log("opf", i), M.groupEnd();
305
+ let s = i.renditionLayoutMeta?.trim(), c = s === "reflowable" || s === "pre-paginated" ? s : o.renditionLayout, l = i.title?.trim() || e.records.find(({ dir: e }) => e)?.basename || "", u = o.readingDirection ?? r.readingDirection, d = (await V({
306
+ archive: e,
307
+ archiveOpf: n
308
+ })).reduce((e, t) => t.size + e, 0), f = i.guide, p = [];
309
+ for (let e of f) {
310
+ let t = Ie(e.type);
311
+ t !== void 0 && p.push({
312
+ href: e.href,
313
+ title: e.title,
314
+ type: t
315
+ });
316
+ }
317
+ return {
318
+ filename: e.filename,
319
+ renditionLayout: c,
320
+ renditionFlow: Pe(i.renditionFlowMeta),
321
+ renditionSpread: Fe(i.renditionSpreadMeta),
322
+ title: l,
323
+ readingDirection: u,
324
+ spineItems: i.spineRows.map((n, r) => {
325
+ let i = e.records.find((e) => e.uri.endsWith(n.href))?.size || 0, o = t || (/^https?:\/\//.test(n.href) ? "" : "file://");
326
+ return {
327
+ id: n.id,
328
+ index: r,
329
+ href: n.href.startsWith("https://") ? n.href : a ? `${o}${a}/${n.href}` : `${o}${n.href}`,
330
+ renditionLayout: n.renditionLayout ?? c,
331
+ ...n.renditionFlow === void 0 ? {} : { renditionFlow: n.renditionFlow },
332
+ progressionWeight: i / d,
333
+ pageSpreadLeft: n.pageSpreadLeft,
334
+ pageSpreadRight: n.pageSpreadRight,
335
+ mediaType: n.mediaType
336
+ };
337
+ }),
338
+ items: H(i.manifestItems, e, (e) => /^https?:\/\//.test(e) ? "" : t || "file://"),
339
+ guide: p.length > 0 ? p : void 0
340
+ };
341
+ }, Re = (e) => {
342
+ let t = e.descendantWithPath("head")?.childrenNamed("meta").find((e) => e.attr.name === "viewport");
343
+ return !!(t && t.attr.name === "viewport");
344
+ }, ze = (e) => e.reduce(async (e, t) => {
345
+ if (!await e || !i({
346
+ mimeType: t.encodingFormat,
347
+ uri: t.uri
348
+ })) return !1;
349
+ let n = t.dir ? null : await t.string();
350
+ return n ? Re(new h(n)) : !1;
351
+ }, Promise.resolve(!0)), Be = ({ archive: e, archiveOpf: t }) => async (n) => n.renditionLayout === "reflowable" && n.spineItems.every((e) => e.renditionLayout === "reflowable") && await ze(await V({
352
+ archive: e,
353
+ archiveOpf: t
354
+ })) ? {
355
+ ...n,
356
+ spineItems: n.spineItems.map((e) => ({
357
+ ...e,
358
+ renditionLayout: "pre-paginated"
359
+ })),
360
+ renditionLayout: "pre-paginated"
361
+ } : n, Ve = () => (e) => ({
362
+ ...e,
363
+ readingDirection: e.readingDirection ?? "ltr"
364
+ }), He = async (e) => {
365
+ let t;
366
+ return await Promise.all(e.records.map(async (e) => {
367
+ if (e.dir || !e.uri.endsWith(l)) return;
368
+ let n = await e.string();
369
+ try {
370
+ let { renditionLayout: e } = f(n);
371
+ e && (t = e);
372
+ } catch (e) {
373
+ console.error(`Unable to parse ${l} for content\n`, n), console.error(e);
374
+ }
375
+ })), {
376
+ kind: "kobo",
377
+ ...t === void 0 ? {} : { renditionLayout: t }
378
+ };
379
+ }, Ue = ({ archive: e }) => async (t) => {
380
+ let { renditionLayout: n } = m(await He(e));
381
+ return {
382
+ ...t,
383
+ renditionLayout: t.renditionLayout ?? n
384
+ };
385
+ }, U = (e) => e.toLowerCase().endsWith(".opf"), We = (e) => e.records.some((e) => !e.dir && (U(e.basename) || U(e.uri))), Ge = ({ archive: e }) => async (n) => We(e) ? n : {
386
+ ...n,
387
+ spineItems: n.spineItems.map((n) => {
388
+ let i = e.records.find((e) => decodeURI(n.href).endsWith(e.uri)), o = a(i?.encodingFormat ?? "") || t(i?.basename ?? "");
389
+ return {
390
+ ...n,
391
+ renditionLayout: o && r(o) ? "pre-paginated" : n.renditionLayout
392
+ };
393
+ })
394
+ }, W = (e) => e ? e.children.map((e) => e instanceof ne ? e.text : e instanceof te ? W(e) : "").join("").trim() : "", Ke = (e) => ee(e.properties).includes("nav"), G = (e, { basePath: t, baseUrl: n }) => {
395
+ let r = {
396
+ contents: [],
397
+ path: "",
398
+ href: "",
399
+ title: ""
400
+ }, i = e.childNamed("span") || e.childNamed("a");
401
+ r.title = (i?.attr.title || i?.val.trim() || W(i)) ?? "";
402
+ let a = i?.name;
403
+ a !== "a" && (i = e.descendantWithPath(`${a}.a`), i && (a = i.name.toLowerCase())), a === "a" && i?.attr.href && (r.path = o(t, i.attr.href), r.href = o(n, t, i.attr.href));
404
+ let s = e.childNamed("ol");
405
+ if (s) {
406
+ let e = s.childrenNamed("li");
407
+ e && e.length > 0 && (r.contents = e.map((e) => G(e, {
408
+ basePath: t,
409
+ baseUrl: n
410
+ })));
411
+ }
412
+ return r;
413
+ }, qe = (e, { basePath: t, baseUrl: n }) => {
414
+ let r = [], i;
415
+ return e.descendantWithPath("body.nav.ol") ? i = e.descendantWithPath("body.nav.ol")?.children : e.descendantWithPath("body.section.nav.ol") && (i = e.descendantWithPath("body.section.nav.ol")?.children), i && i.length > 0 && i.filter((e) => e.name === "li").forEach((e) => {
416
+ r.push(G(e, {
417
+ basePath: t,
418
+ baseUrl: n
419
+ }));
420
+ }), r;
421
+ }, Je = async (e, t, { baseUrl: n }) => {
422
+ let r = e.manifestItems.find(Ke);
423
+ if (r?.href) {
424
+ let e = Object.values(t.records).find((e) => e.uri.endsWith(r.href));
425
+ if (e && !e.dir) return qe(new h(await e.string()), {
426
+ basePath: j(e.uri),
427
+ baseUrl: n
428
+ });
429
+ }
430
+ }, K = (e, { opfBasePath: t, baseUrl: n, prefix: r }) => {
431
+ let i = e?.childNamed(`${r}content`)?.attr.src || "", a = {
432
+ title: e?.descendantWithPath(`${r}navLabel.${r}text`)?.val || "",
433
+ path: o(t, i),
434
+ href: o(n, t, i),
435
+ contents: []
436
+ }, s = e.childrenNamed(`${r}navPoint`);
437
+ return s && s.length > 0 && (a.contents = s.map((e) => K(e, {
438
+ opfBasePath: t,
439
+ baseUrl: n,
440
+ prefix: r
441
+ }))), a;
442
+ }, Ye = (e, { opfBasePath: t, baseUrl: n }) => {
443
+ let r = [], i = e.name, a = "";
444
+ return i.indexOf(":") !== -1 && (a = `${i.split(":")[0]}:`), e.childNamed(`${a}navMap`)?.childrenNamed(`${a}navPoint`).forEach((e) => {
445
+ r.push(K(e, {
446
+ opfBasePath: t,
447
+ baseUrl: n,
448
+ prefix: a
449
+ }));
450
+ }), r;
451
+ }, Xe = async ({ opf: e, opfBasePath: t, baseUrl: n, archive: r }) => {
452
+ let i = e.spineTocIdref;
453
+ if (i) {
454
+ let a = e.manifestItems.find((e) => e.id === i);
455
+ if (a) {
456
+ let e = `${t}${t === "" ? "" : "/"}${a.href}`, i = Object.values(r.records).find((t) => t.uri.endsWith(e));
457
+ if (i && !i.dir) return Ye(new h(await i.string()), {
458
+ opfBasePath: t,
459
+ baseUrl: n
460
+ });
461
+ }
462
+ }
463
+ }, Ze = async (e, t, { baseUrl: n }) => {
464
+ let { basePath: r } = z(t) || {}, i = await Je(e, t, { baseUrl: n });
465
+ if (i) return i;
466
+ let a = await Xe({
467
+ opf: e,
468
+ opfBasePath: r ?? "",
469
+ archive: t,
470
+ baseUrl: n
471
+ });
472
+ if (a) return a;
473
+ }, Qe = (e) => e.replace(/\.[^.]+$/, "").replace(/[_-]/g, " ").replace(/\s+/g, " ").trim(), $e = (e, n) => {
474
+ if (e.spineItems.length !== 0 && e.spineItems.every((e) => (a(e.mediaType ?? "") || t(e.href))?.startsWith("audio/"))) return e.spineItems.map((e) => {
475
+ let t = n.records.find((t) => !t.dir && decodeURI(e.href).endsWith(t.uri));
476
+ return {
477
+ title: Qe(t?.basename ?? e.href),
478
+ href: e.href,
479
+ path: t?.uri ?? e.href,
480
+ contents: []
481
+ };
482
+ });
483
+ }, et = (e, { baseUrl: t }) => {
484
+ let n = [...e.records].sort((e, t) => O(e.uri, t.uri)), r = (e, t, n, i, a) => {
485
+ let o = e.find((e) => e.title === t), [s, ...c] = n;
486
+ return o ? s ? [...e.filter((e) => e !== o), {
487
+ ...o,
488
+ contents: [...o.contents, ...r(o.contents, s, c, i, a)]
489
+ }] : o.path.split("/").length > a.split("/").length ? [...e.filter((e) => e !== o), {
490
+ ...o,
491
+ path: a,
492
+ href: i
493
+ }] : e : s ? [...e, {
494
+ contents: r([], s, c, i, a),
495
+ href: i,
496
+ path: a,
497
+ title: t
498
+ }] : [...e, {
499
+ contents: [],
500
+ href: i,
501
+ path: a,
502
+ title: t
503
+ }];
504
+ };
505
+ return n.reduce((e, n) => {
506
+ if (n.dir) return e;
507
+ let [i, ...a] = n.uri.split("/").slice(0, -1);
508
+ return i ? r(e, i, a, o(t, encodeURI(n.uri)).replace(/\/$/, ""), n.uri.replace(/\/$/, "")) : e;
509
+ }, []);
510
+ }, tt = async (e, t, { baseUrl: n, archiveOpf: r }) => {
511
+ if (r) return await Ze(r.opf, e, { baseUrl: n }) || [];
512
+ let i = $e(t, e);
513
+ if (i) return i;
514
+ let a = et(e, { baseUrl: n });
515
+ if (a.length !== 0) return a;
516
+ }, nt = ({ archive: e, baseUrl: t, archiveOpf: n }) => async (r) => {
517
+ if (r.nav) return r;
518
+ let i = await tt(e, r, {
519
+ baseUrl: t,
520
+ archiveOpf: n
521
+ });
522
+ return i ? {
523
+ ...r,
524
+ nav: { toc: i }
525
+ } : r;
526
+ }, rt = (e) => e ? e.endsWith("/") ? e : `${e}/` : "", q = async (e, { baseUrl: t = "", hooks: n = {} } = {}) => {
527
+ M.log("Generating manifest from archive", e);
528
+ let r = await B(e), i = rt(t), a = (t) => (t ?? []).map((t) => t({
529
+ archive: e,
530
+ baseUrl: i
531
+ })), o = [
532
+ Le({
533
+ archive: e,
534
+ baseUrl: i,
535
+ archiveOpf: r
536
+ }),
537
+ je({
538
+ archive: e,
539
+ baseUrl: i
540
+ }),
541
+ ke({
542
+ archive: e,
543
+ baseUrl: i
544
+ }),
545
+ Ge({
546
+ archive: e,
547
+ baseUrl: i
548
+ }),
549
+ ...a(n.content)
550
+ ], s = a(n.spine), c = [
551
+ Be({
552
+ archive: e,
553
+ baseUrl: i,
554
+ archiveOpf: r
555
+ }),
556
+ Ue({
557
+ archive: e,
558
+ baseUrl: i
559
+ }),
560
+ ...a(n.presentation)
561
+ ], l = [nt({
562
+ archive: e,
563
+ baseUrl: i,
564
+ archiveOpf: r
565
+ }), ...a(n.navigation)], u = [
566
+ ...o,
567
+ ...s,
568
+ ...c,
569
+ ...l,
570
+ Ve()
571
+ ];
572
+ try {
573
+ let t = Ne({
574
+ archive: e,
575
+ baseUrl: i
576
+ })(), n = await u.reduce(async (e, t) => await t(await e), t);
577
+ if (M.log("Generated manifest", n), process.env.NODE_ENV === "development" && M.isEnabled()) {
578
+ let e = JSON.stringify(n, null, 2);
579
+ M.groupCollapsed(...M.getGroupArgs("Generated manifest")), M.log(`\n${e}`), M.groupEnd();
580
+ }
581
+ return n;
582
+ } catch (e) {
583
+ throw M.error(e), e;
584
+ }
585
+ }, it = (e) => {
586
+ let t = e.descendantWithPath("head")?.childrenNamed("meta").find((e) => e.attr.name === "calibre:cover");
587
+ return !!(t && t.attr.name === "calibre:cover");
588
+ }, at = (e) => e.descendantWithPath("body")?.descendantWithPath("div")?.childrenNamed("svg")?.find((e) => e.attr.width === "100%" && e.attr.preserveAspectRatio === "none"), ot = ({ archive: e, resourcePath: t }) => async (n) => {
589
+ let r = Object.values(e.records).find((e) => e.uri === t && !e.dir);
590
+ if (r && !r.dir && r.basename.endsWith(".xhtml")) {
591
+ let e = new h(typeof n.body == "string" ? n.body : await r.string());
592
+ if (it(e)) {
593
+ let t = at(e);
594
+ return t && delete t.attr.preserveAspectRatio, {
595
+ ...n,
596
+ body: e?.toString()
597
+ };
598
+ }
599
+ }
600
+ return n;
601
+ }, st = ({ archive: e, resourcePath: t }) => async (n) => ot({
602
+ archive: e,
603
+ resourcePath: t
604
+ })(n), ct = ({ archive: e, resourcePath: t }) => async (n) => {
605
+ let r = Object.values(e.records).find((e) => e.uri === t && !e.dir);
606
+ if (r && !r.dir && r.basename.endsWith(".css")) {
607
+ let e = (typeof n.body == "string" ? n.body : await r.string()).replaceAll("-webkit-writing-mode", "writing-mode");
608
+ return {
609
+ ...n,
610
+ body: e
611
+ };
612
+ }
613
+ return n;
614
+ }, lt = async (e, t) => {
615
+ let n = await B(e);
616
+ if (n) {
617
+ let { opf: r } = n, i = H(r.manifestItems, e, () => "");
618
+ if (i.find((e) => t.endsWith(e.href))?.mediaType) return { mediaType: i.find((e) => t.endsWith(e.href))?.mediaType };
619
+ }
620
+ return { mediaType: ut(t) };
621
+ }, ut = (e) => {
622
+ if (e.endsWith(".css")) return "text/css; charset=UTF-8";
623
+ if (e.endsWith(".jpg")) return "image/jpg";
624
+ if (e.endsWith(".xhtml")) return "application/xhtml+xml";
625
+ if (e.endsWith(".mp4")) return "video/mp4";
626
+ if (e.endsWith(".svg")) return "image/svg+xml";
627
+ }, dt = ({ archive: e, resourcePath: t }) => async (n) => {
628
+ let r = Object.values(e.records).find((e) => e.uri === t && !e.dir);
629
+ if (!r || r.dir) return n;
630
+ let i = await lt(e, t);
631
+ return {
632
+ ...n,
633
+ params: {
634
+ ...n.params,
635
+ ...r?.encodingFormat && { contentType: r.encodingFormat },
636
+ ...i.mediaType && { contentType: i.mediaType }
637
+ }
638
+ };
639
+ }, J = /* @__PURE__ */ "div.span.p.a.li.ul.ol.h1.h2.h3.h4.h5.h6.table.tr.td.th.thead.tbody.tfoot.section.article.header.footer.nav.aside.main.figure.figcaption.blockquote.pre.code.form.textarea.select.option.button.label.fieldset.legend.caption.dl.dt.dd.iframe.video.audio.canvas.script.style".split("."), ft = ({ archive: e, resourcePath: t }) => async (n) => {
640
+ let r = Object.values(e.records).find((e) => e.uri === t && !e.dir);
641
+ if (r && !r.dir && r.basename.endsWith(".xhtml")) {
642
+ let e = typeof n.body == "string" ? n.body : await r.string();
643
+ if (!RegExp(`<(${J.join("|")})[\\s/>]`, "i").test(e)) return n;
644
+ let t = RegExp(`<(${J.join("|")})(\\s[^>]*)?\\s*/>`, "gi"), i = e.replace(t, (e, t, n = "") => `<${t} ${n.trim()}></${t}>`);
645
+ return {
646
+ ...n,
647
+ body: i
648
+ };
649
+ }
650
+ return n;
651
+ }, Y = async (e, t, { hooks: n = [] } = {}) => {
652
+ let r = { params: {} }, i = [
653
+ ...n.map((n) => n({
654
+ archive: e,
655
+ resourcePath: t
656
+ })),
657
+ dt({
658
+ archive: e,
659
+ resourcePath: t
660
+ }),
661
+ ft({
662
+ archive: e,
663
+ resourcePath: t
664
+ }),
665
+ ct({
666
+ archive: e,
667
+ resourcePath: t
668
+ }),
669
+ st({
670
+ archive: e,
671
+ resourcePath: t
672
+ })
673
+ ];
674
+ try {
675
+ let n = await i.reduce(async (e, t) => await t(await e), Promise.resolve(r));
676
+ if (M.log("Generated resource", t, n), n.body !== void 0) return n;
677
+ let a = Object.values(e.records).find((e) => e.uri === t && !e.dir);
678
+ if (!a || a.dir) throw Error(`no file found for resourcePath:${t}`);
679
+ return {
680
+ ...n,
681
+ body: await a.blob()
682
+ };
683
+ } catch (e) {
684
+ throw M.error(e), e;
685
+ }
686
+ }, pt = class {
687
+ constructor(e) {
688
+ this.cleanArchiveAfter = e, this.state$ = new re({
689
+ status: "idle",
690
+ locks: 0
691
+ });
692
+ }
693
+ update(e) {
694
+ this.state$.next({
695
+ ...this.state$.getValue(),
696
+ ...e
697
+ });
698
+ }
699
+ get locks$() {
700
+ return this.state$.pipe(C(({ locks: e }) => e));
701
+ }
702
+ get state() {
703
+ return this.state$.getValue();
704
+ }
705
+ get isUnlocked$() {
706
+ return this.locks$.pipe(C((e) => e <= 0), ie(), ue());
707
+ }
708
+ get overTTL$() {
709
+ return this.isUnlocked$.pipe(E((e) => e ? this.cleanArchiveAfter === Infinity ? _ : pe(this.cleanArchiveAfter) : _));
710
+ }
711
+ }, mt = ({ getArchive: e, cleanArchiveAfter: t = 300 * 1e3 }) => {
712
+ let n = new v(), r = new v(), i = new v(), a = {};
713
+ return n.pipe(T((t) => {
714
+ let n = a[t];
715
+ if (!n || n.state.status !== "idle") return g;
716
+ let r = !1, o = (e) => {
717
+ M.debug(`Cleaning up archive with key: ${e}`);
718
+ let t = a[e];
719
+ delete a[e], r ||= (t?.state.archive?.close(), !0);
720
+ };
721
+ n.update({ status: "loading" });
722
+ let s = n.locks$, c = n.isUnlocked$, l = s.pipe(le(), b(([e, t]) => t > e), de(!0));
723
+ return S(e(t)).pipe(D((e) => {
724
+ n.update({
725
+ archive: e,
726
+ status: "success"
727
+ });
728
+ }), y((e) => (o(t), n.update({
729
+ status: "error",
730
+ error: e
731
+ }), g)), E(() => w(l.pipe(E(() => i), E(() => c), b((e) => e)), n.overTTL$).pipe(x(), D(() => {
732
+ o(t);
733
+ }))));
734
+ }), fe(r)).subscribe(), {
735
+ access: (e) => {
736
+ let r = !1, i = a[e] ?? new pt(t);
737
+ a[e] = i, i.update({ locks: i.state.locks + 1 });
738
+ let o = () => {
739
+ r || (r = !0, i.update({ locks: i.state.locks - 1 }));
740
+ };
741
+ return n.next(e), w(i.state$.pipe(C(({ archive: e }) => e), b((e) => !!e)), i.state$.pipe(D(({ error: e }) => {
742
+ if (e) throw e;
743
+ }), oe())).pipe(x(), C((e) => ({
744
+ archive: e,
745
+ release: o
746
+ })), y((e) => {
747
+ throw o(), e;
748
+ }));
749
+ },
750
+ purge: () => {
751
+ i.next();
752
+ },
753
+ _archives: a
754
+ };
755
+ }, X = (e) => e ? /^\d+$/.test(e) ? {
756
+ valid: !0,
757
+ value: Number.parseInt(e, 10)
1019
758
  } : {
1020
- valid: !1,
1021
- value: void 0
759
+ valid: !1,
760
+ value: void 0
1022
761
  } : {
1023
- valid: !0,
1024
- value: void 0
1025
- }, xt = (e) => {
1026
- if (!e.toLowerCase().startsWith("bytes="))
1027
- return {
1028
- kind: "missing"
1029
- };
1030
- const t = e.slice(6).trim();
1031
- if (!t)
1032
- return {
1033
- kind: "invalid"
1034
- };
1035
- if (t.includes(","))
1036
- return {
1037
- kind: "multi"
1038
- };
1039
- const o = /^(\d*)-(\d*)$/.exec(t);
1040
- if (!o)
1041
- return {
1042
- kind: "invalid"
1043
- };
1044
- const [, r = "", n = ""] = o, s = G(r.trim()), i = G(n.trim());
1045
- return !s.valid || !i.valid ? {
1046
- kind: "invalid"
1047
- } : {
1048
- kind: "single",
1049
- start: s.value,
1050
- end: i.value
1051
- };
1052
- }, Et = (e) => {
1053
- if (e instanceof Blob)
1054
- return {
1055
- size: e.size,
1056
- slice: (o, r) => {
1057
- const n = e.slice(o, r);
1058
- return { content: n, length: n.size };
1059
- }
1060
- };
1061
- const t = new TextEncoder().encode(e);
1062
- return {
1063
- size: t.byteLength,
1064
- slice: (o, r) => {
1065
- const n = t.slice(o, r);
1066
- return { content: n, length: n.byteLength };
1067
- }
1068
- };
1069
- }, kt = ({
1070
- body: e,
1071
- contentType: t,
1072
- rangeHeader: o
1073
- }) => {
1074
- const r = new Headers();
1075
- if (t && r.set("Content-Type", t), r.set("Accept-Ranges", "bytes"), !o)
1076
- return e instanceof Blob && r.set("Content-Length", String(e.size)), new Response(e, {
1077
- status: 200,
1078
- headers: r
1079
- });
1080
- const n = xt(o);
1081
- if (n.kind === "missing" || n.kind === "multi")
1082
- return e instanceof Blob && r.set("Content-Length", String(e.size)), new Response(e, {
1083
- status: 200,
1084
- headers: r
1085
- });
1086
- const s = Et(e), i = s.size;
1087
- if (n.kind === "invalid")
1088
- return new Response(null, {
1089
- status: 416,
1090
- headers: {
1091
- "Content-Range": `bytes */${i}`
1092
- }
1093
- });
1094
- let a = n.start, c = n.end;
1095
- if (a === void 0 && c === void 0)
1096
- return new Response(null, {
1097
- status: 416,
1098
- headers: {
1099
- "Content-Range": `bytes */${i}`
1100
- }
1101
- });
1102
- if (a === void 0) {
1103
- const u = Math.min(c ?? 0, i);
1104
- a = Math.max(0, i - u), c = i - 1;
1105
- } else (c === void 0 || c >= i) && (c = i - 1);
1106
- if (a < 0 || c < 0 || a >= i || c >= i || a > c)
1107
- return new Response(null, {
1108
- status: 416,
1109
- headers: {
1110
- "Content-Range": `bytes */${i}`
1111
- }
1112
- });
1113
- const d = s.slice(a, c + 1);
1114
- return r.set("Content-Length", String(d.length)), r.set("Content-Range", `bytes ${a}-${c}/${i}`), new Response(d.content, {
1115
- status: 206,
1116
- headers: r
1117
- });
1118
- }, K = "file://", Ct = /^https?:\/\//, Wt = (e) => {
1119
- try {
1120
- return decodeURIComponent(e);
1121
- } catch {
1122
- return e;
1123
- }
1124
- }, q = (e) => e.startsWith(K) ? e.slice(K.length) : e, Pt = (e) => {
1125
- const t = q(e);
1126
- return Ct.test(t) ? t : q(Wt(t));
1127
- };
1128
- class _t {
1129
- constructor({
1130
- hooks: t,
1131
- onError: o,
1132
- onManifestSuccess: r,
1133
- ...n
1134
- }) {
1135
- this.onError = (s) => (console.error(s), new Response(String(s), { status: 500 })), this.archiveLoader = Lt(n), this.hooks = t ?? {}, this.onManifestSuccess = r ?? (({ manifest: s }) => Promise.resolve(s)), this.onError = o ?? this.onError;
1136
- }
1137
- prune() {
1138
- this.archiveLoader.purge();
1139
- }
1140
- accessArchive(t) {
1141
- return this.lastAccessedKey !== void 0 && this.lastAccessedKey !== t && this.archiveLoader.purge(), this.lastAccessedKey = t, this.archiveLoader.access(t);
1142
- }
1143
- accessArchiveWithoutLock(t) {
1144
- return this.accessArchive(t).pipe(
1145
- $(({ archive: o, release: r }) => (r(), o))
1146
- );
1147
- }
1148
- withArchiveResponse({
1149
- key: t,
1150
- getResponse: o
1151
- }) {
1152
- const r = this.accessArchive(t).pipe(
1153
- Y(
1154
- ({ archive: n, release: s }) => F(o(n)).pipe(
1155
- Ie(() => {
1156
- s();
1157
- })
1158
- )
1159
- ),
1160
- C((n) => Te(this.onError(n)))
1161
- );
1162
- return Se(r);
1163
- }
1164
- fetchManifest({ key: t, baseUrl: o }) {
1165
- return this.withArchiveResponse({
1166
- key: t,
1167
- getResponse: (r) => F(
1168
- gt(r, {
1169
- baseUrl: o,
1170
- hooks: this.hooks.manifest
1171
- })
1172
- ).pipe(
1173
- I(
1174
- (s) => F(this.onManifestSuccess({ manifest: s, archive: r }))
1175
- ),
1176
- $(
1177
- (s) => new Response(JSON.stringify(s), {
1178
- status: 200
1179
- })
1180
- )
1181
- )
1182
- });
1183
- }
1184
- fetchResource({
1185
- key: t,
1186
- resourcePath: o,
1187
- request: r
1188
- }) {
1189
- return this.withArchiveResponse({
1190
- key: t,
1191
- getResponse: (n) => {
1192
- const s = Pt(o);
1193
- return F(
1194
- St(n, s, {
1195
- hooks: this.hooks.resource
1196
- })
1197
- ).pipe(
1198
- $(
1199
- (a) => kt({
1200
- body: a.body ?? "",
1201
- contentType: a.params.contentType,
1202
- rangeHeader: r?.headers.get("range")
1203
- })
1204
- )
1205
- );
1206
- }
1207
- });
1208
- }
1209
- }
1210
- class Vt extends _t {
1211
- constructor({
1212
- getUriInfo: t,
1213
- ...o
1214
- }) {
1215
- super(o), this.getUriInfo = t, this.fetchEventListener = this.fetchEventListener.bind(this);
1216
- }
1217
- fetchEventListener(t) {
1218
- try {
1219
- const o = this.getUriInfo(t);
1220
- if (!o) return;
1221
- const r = j(o.baseUrl), n = t.request.url.substring(
1222
- r.length + 1
1223
- ), [s = ""] = n.split("/"), i = j(
1224
- n.substring(s.length + 1)
1225
- );
1226
- n.endsWith("/manifest") ? t.respondWith(
1227
- this.fetchManifest({ key: s, baseUrl: `${r}/${s}/` })
1228
- ) : t.respondWith(
1229
- this.fetchResource({
1230
- key: s,
1231
- resourcePath: i,
1232
- request: t.request
1233
- })
1234
- );
1235
- } catch (o) {
1236
- t.respondWith(new Response(String(o), { status: 500 }));
1237
- }
1238
- }
1239
- }
1240
- export {
1241
- Vt as ServiceWorkerStreamer,
1242
- _t as Streamer,
1243
- Xt as configure,
1244
- Dt as createArchiveFromArrayBufferList,
1245
- Bt as createArchiveFromJszip,
1246
- jt as createArchiveFromLibArchive,
1247
- Ut as createArchiveFromText,
1248
- Ht as createArchiveFromUrls,
1249
- Ne as createUniqueXmlSafeId,
1250
- _e as createXmlSafeId,
1251
- Q as createXmlSafeIdFactory,
1252
- gt as generateManifestFromArchive,
1253
- St as generateResourceFromArchive,
1254
- Me as getArchiveHasComicInfo,
1255
- _ as getArchiveOpfInfo,
1256
- Re as getUriBasePath,
1257
- A as getUriBasename,
1258
- j as removeTrailingSlash,
1259
- P as sortByTitleComparator
762
+ valid: !0,
763
+ value: void 0
764
+ }, ht = (e) => {
765
+ if (!e.toLowerCase().startsWith("bytes=")) return { kind: "missing" };
766
+ let t = e.slice(6).trim();
767
+ if (!t) return { kind: "invalid" };
768
+ if (t.includes(",")) return { kind: "multi" };
769
+ let n = /^(\d*)-(\d*)$/.exec(t);
770
+ if (!n) return { kind: "invalid" };
771
+ let [, r = "", i = ""] = n, a = X(r.trim()), o = X(i.trim());
772
+ return !a.valid || !o.valid ? { kind: "invalid" } : {
773
+ kind: "single",
774
+ start: a.value,
775
+ end: o.value
776
+ };
777
+ }, gt = (e) => {
778
+ if (e instanceof Blob) return {
779
+ size: e.size,
780
+ slice: (t, n) => {
781
+ let r = e.slice(t, n);
782
+ return {
783
+ content: r,
784
+ length: r.size
785
+ };
786
+ }
787
+ };
788
+ let t = new TextEncoder().encode(e);
789
+ return {
790
+ size: t.byteLength,
791
+ slice: (e, n) => {
792
+ let r = t.slice(e, n);
793
+ return {
794
+ content: r,
795
+ length: r.byteLength
796
+ };
797
+ }
798
+ };
799
+ }, _t = ({ body: e, contentType: t, rangeHeader: n }) => {
800
+ let r = new Headers();
801
+ if (t && r.set("Content-Type", t), r.set("Accept-Ranges", "bytes"), !n) return e instanceof Blob && r.set("Content-Length", String(e.size)), new Response(e, {
802
+ status: 200,
803
+ headers: r
804
+ });
805
+ let i = ht(n);
806
+ if (i.kind === "missing" || i.kind === "multi") return e instanceof Blob && r.set("Content-Length", String(e.size)), new Response(e, {
807
+ status: 200,
808
+ headers: r
809
+ });
810
+ let a = gt(e), o = a.size;
811
+ if (i.kind === "invalid") return new Response(null, {
812
+ status: 416,
813
+ headers: { "Content-Range": `bytes */${o}` }
814
+ });
815
+ let s = i.start, c = i.end;
816
+ if (s === void 0 && c === void 0 || (s === void 0 ? (s = Math.max(0, o - Math.min(c ?? 0, o)), c = o - 1) : (c === void 0 || c >= o) && (c = o - 1), s < 0 || c < 0 || s >= o || c >= o || s > c)) return new Response(null, {
817
+ status: 416,
818
+ headers: { "Content-Range": `bytes */${o}` }
819
+ });
820
+ let l = a.slice(s, c + 1);
821
+ return r.set("Content-Length", String(l.length)), r.set("Content-Range", `bytes ${s}-${c}/${o}`), new Response(l.content, {
822
+ status: 206,
823
+ headers: r
824
+ });
825
+ }, Z = "file://", vt = /^https?:\/\//, yt = (e) => {
826
+ try {
827
+ return decodeURIComponent(e);
828
+ } catch {
829
+ return e;
830
+ }
831
+ }, Q = (e) => e.startsWith(Z) ? e.slice(Z.length) : e, bt = (e) => {
832
+ let t = Q(e);
833
+ return vt.test(t) ? t : Q(yt(t));
834
+ }, $ = class {
835
+ constructor({ hooks: e, onError: t, onManifestSuccess: n, ...r }) {
836
+ this.onError = (e) => (console.error(e), new Response(String(e), { status: 500 })), this.archiveLoader = mt(r), this.hooks = e ?? {}, this.onManifestSuccess = n ?? (({ manifest: e }) => Promise.resolve(e)), this.onError = t ?? this.onError;
837
+ }
838
+ prune() {
839
+ this.archiveLoader.purge();
840
+ }
841
+ accessArchive(e) {
842
+ return this.lastAccessedKey !== void 0 && this.lastAccessedKey !== e && this.archiveLoader.purge(), this.lastAccessedKey = e, this.archiveLoader.access(e);
843
+ }
844
+ accessArchiveWithoutLock(e) {
845
+ return this.accessArchive(e).pipe(C(({ archive: e, release: t }) => (t(), e)));
846
+ }
847
+ withArchiveResponse({ key: e, getResponse: t }) {
848
+ return se(this.accessArchive(e).pipe(T(({ archive: e, release: n }) => S(t(e)).pipe(ae(() => {
849
+ n();
850
+ }))), y((e) => ce(this.onError(e)))));
851
+ }
852
+ fetchManifest({ key: e, baseUrl: t }) {
853
+ return this.withArchiveResponse({
854
+ key: e,
855
+ getResponse: (e) => S(q(e, {
856
+ baseUrl: t,
857
+ hooks: this.hooks.manifest
858
+ })).pipe(E((t) => S(this.onManifestSuccess({
859
+ manifest: t,
860
+ archive: e
861
+ }))), C((e) => new Response(JSON.stringify(e), { status: 200 })))
862
+ });
863
+ }
864
+ fetchResource({ key: e, resourcePath: t, request: n }) {
865
+ return this.withArchiveResponse({
866
+ key: e,
867
+ getResponse: (e) => S(Y(e, bt(t), { hooks: this.hooks.resource })).pipe(C((e) => _t({
868
+ body: e.body ?? "",
869
+ contentType: e.params.contentType,
870
+ rangeHeader: n?.headers.get("range")
871
+ })))
872
+ });
873
+ }
874
+ }, xt = class extends $ {
875
+ constructor({ getUriInfo: e, ...t }) {
876
+ super(t), this.getUriInfo = e, this.fetchEventListener = this.fetchEventListener.bind(this);
877
+ }
878
+ fetchEventListener(e) {
879
+ try {
880
+ let t = this.getUriInfo(e);
881
+ if (!t) return;
882
+ let n = A(t.baseUrl), r = e.request.url.substring(n.length + 1), [i = ""] = r.split("/"), a = A(r.substring(i.length + 1));
883
+ r.endsWith("/manifest") ? e.respondWith(this.fetchManifest({
884
+ key: i,
885
+ baseUrl: `${n}/${i}/`
886
+ })) : e.respondWith(this.fetchResource({
887
+ key: i,
888
+ resourcePath: a,
889
+ request: e.request
890
+ }));
891
+ } catch (t) {
892
+ e.respondWith(new Response(String(t), { status: 500 }));
893
+ }
894
+ }
1260
895
  };
1261
- //# sourceMappingURL=index.js.map
896
+ //#endregion
897
+ export { xt as ServiceWorkerStreamer, $ as Streamer, De as configure, me as createArchiveFromArrayBufferList, ge as createArchiveFromJszip, _e as createArchiveFromLibArchive, ve as createArchiveFromText, we as createArchiveFromUrls, I as createUniqueXmlSafeId, F as createXmlSafeId, L as createXmlSafeIdFactory, q as generateManifestFromArchive, Y as generateResourceFromArchive, R as getArchiveHasComicInfo, z as getArchiveOpfInfo, j as getUriBasePath, k as getUriBasename, A as removeTrailingSlash, O as sortByTitleComparator };
898
+
899
+ //# sourceMappingURL=index.js.map