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