@prose-reader/streamer 1.20.0 → 1.22.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.
@@ -1,405 +1,631 @@
1
- import h from "xmldoc";
2
- import { urlJoin as v, isXmlBasedMimeType as G, detectMimeTypeFromName as z } from "@prose-reader/shared";
3
- const O = (e, { opfBasePath: i, baseUrl: n }) => {
4
- const a = {
1
+ import { urlJoin, PROSE_READER_RESOURCE_ERROR_INJECTED_META_NAME, isXmlBasedMimeType, detectMimeTypeFromName } from "@prose-reader/shared";
2
+ import xmldoc from "xmldoc";
3
+ let enabled = false;
4
+ const Report = {
5
+ enable: (enable) => {
6
+ enabled = enable;
7
+ },
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+ log: (...data) => {
10
+ if (enabled) {
11
+ console.log(`[prose-reader-streamer]`, ...data);
12
+ }
13
+ },
14
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
+ warn: (...data) => {
16
+ if (enabled) {
17
+ console.warn(`[prose-reader-streamer]`, ...data);
18
+ }
19
+ },
20
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
+ error: (...data) => {
22
+ console.error(...data);
23
+ },
24
+ time: (label) => {
25
+ if (enabled) {
26
+ console.time(`[prose-reader-streamer] [metric] ${label}`);
27
+ }
28
+ },
29
+ timeEnd: (label) => {
30
+ if (enabled) {
31
+ console.timeEnd(`[prose-reader-streamer] [metric] ${label}`);
32
+ }
33
+ },
34
+ metric: (performanceEntry, targetDuration = Infinity) => {
35
+ const duration = typeof performanceEntry === `number` ? performanceEntry : performanceEntry.duration;
36
+ if (enabled) {
37
+ if (performanceEntry.duration <= targetDuration) {
38
+ console.log(`[prose-reader-streamer] [metric] `, `${performanceEntry.name} took ${duration}ms`);
39
+ } else {
40
+ console.warn(
41
+ `[prose-reader-streamer] [metric] `,
42
+ `${performanceEntry.name} took ${performanceEntry.duration}ms which is above the ${targetDuration}ms target for this function`
43
+ );
44
+ }
45
+ }
46
+ },
47
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
48
+ measurePerformance: (name, targetDuration = 10, functionToMeasure) => {
49
+ return (...args) => {
50
+ const t0 = performance.now();
51
+ const response = functionToMeasure(...args);
52
+ if (response && response.then) {
53
+ return response.then((res) => {
54
+ const t12 = performance.now();
55
+ Report.metric({ name, duration: t12 - t0 }, targetDuration);
56
+ return res;
57
+ });
58
+ }
59
+ const t1 = performance.now();
60
+ Report.metric({ name, duration: t1 - t0 }, targetDuration);
61
+ return response;
62
+ };
63
+ }
64
+ };
65
+ const cssFixHook = ({ archive, resourcePath }) => async (resource) => {
66
+ const file = Object.values(archive.files).find((file2) => file2.uri === resourcePath);
67
+ if (file == null ? void 0 : file.basename.endsWith(`.css`)) {
68
+ const bodyToParse = resource.body ?? await file.string();
69
+ const newBody = bodyToParse.replaceAll(`-webkit-writing-mode`, `writing-mode`);
70
+ return {
71
+ ...resource,
72
+ body: newBody
73
+ };
74
+ }
75
+ return resource;
76
+ };
77
+ const getArchiveOpfInfo = (archive) => {
78
+ const filesAsArray = Object.values(archive.files).filter((file2) => !file2.dir);
79
+ const file = filesAsArray.find((file2) => file2.uri.endsWith(`.opf`));
80
+ return {
81
+ data: file,
82
+ basePath: (file == null ? void 0 : file.uri.substring(0, file.uri.lastIndexOf(`/`))) || ``
83
+ };
84
+ };
85
+ const extractNavChapter = (li, { opfBasePath, baseUrl }) => {
86
+ const chp = {
5
87
  contents: [],
6
- path: "",
7
- href: "",
8
- title: ""
88
+ path: ``,
89
+ href: ``,
90
+ title: ``
9
91
  };
10
- let t = e.childNamed("span") || e.childNamed("a");
11
- a.title = (t == null ? void 0 : t.attr.title) || (t == null ? void 0 : t.val.trim()) || a.title;
12
- let r = t == null ? void 0 : t.name;
13
- r !== "a" && (t = e.descendantWithPath(`${r}.a`), t && (r = t.name.toLowerCase())), r === "a" && (t != null && t.attr.href) && (a.path = v(i, t.attr.href), a.href = v(n, i, t.attr.href));
14
- const o = e.childNamed("ol");
15
- if (o) {
16
- const s = o.childrenNamed("li");
17
- s && s.length > 0 && (a.contents = s.map((d) => O(d, { opfBasePath: i, baseUrl: n })));
92
+ let contentNode = li.childNamed(`span`) || li.childNamed(`a`);
93
+ chp.title = (contentNode == null ? void 0 : contentNode.attr.title) || (contentNode == null ? void 0 : contentNode.val.trim()) || chp.title;
94
+ let node = contentNode == null ? void 0 : contentNode.name;
95
+ if (node !== `a`) {
96
+ contentNode = li.descendantWithPath(`${node}.a`);
97
+ if (contentNode) {
98
+ node = contentNode.name.toLowerCase();
99
+ }
100
+ }
101
+ if (node === `a` && (contentNode == null ? void 0 : contentNode.attr.href)) {
102
+ chp.path = urlJoin(opfBasePath, contentNode.attr.href);
103
+ chp.href = urlJoin(baseUrl, opfBasePath, contentNode.attr.href);
18
104
  }
19
- return a;
20
- }, J = (e, { opfBasePath: i, baseUrl: n }) => {
21
- var r, o;
22
- const a = [];
23
- let t;
24
- return e.descendantWithPath("body.nav.ol") ? t = (r = e.descendantWithPath("body.nav.ol")) == null ? void 0 : r.children : e.descendantWithPath("body.section.nav.ol") && (t = (o = e.descendantWithPath("body.section.nav.ol")) == null ? void 0 : o.children), t && t.length > 0 && t.filter((s) => s.name === "li").forEach((s) => a.push(O(s, { opfBasePath: i, baseUrl: n }))), a;
25
- }, K = async (e, i, { opfBasePath: n, baseUrl: a }) => {
26
- var r;
27
- const t = (r = e.childNamed("manifest")) == null ? void 0 : r.childrenNamed("item").find((o) => o.attr.properties === "nav");
28
- if (t) {
29
- const o = Object.values(i.files).find((s) => s.uri.endsWith(t.attr.href || ""));
30
- if (o) {
31
- const s = new h.XmlDocument(await o.string());
32
- return J(s, { opfBasePath: n, baseUrl: a });
105
+ const sublistNode = li.childNamed(`ol`);
106
+ if (sublistNode) {
107
+ const children = sublistNode.childrenNamed(`li`);
108
+ if (children && children.length > 0) {
109
+ chp.contents = children.map((child) => extractNavChapter(child, { opfBasePath, baseUrl }));
33
110
  }
34
111
  }
35
- }, X = (e, { opfBasePath: i, baseUrl: n, prefix: a }) => {
36
- var s, d;
37
- const t = ((s = e == null ? void 0 : e.childNamed(`${a}content`)) == null ? void 0 : s.attr.src) || "", r = {
38
- title: ((d = e == null ? void 0 : e.descendantWithPath(`${a}navLabel.${a}text`)) == null ? void 0 : d.val) || "",
39
- path: v(i, t),
40
- href: v(n, i, t),
112
+ return chp;
113
+ };
114
+ const buildTOCFromNav = (doc, { opfBasePath, baseUrl }) => {
115
+ var _a, _b;
116
+ const toc = [];
117
+ let navDataChildren;
118
+ if (doc.descendantWithPath(`body.nav.ol`)) {
119
+ navDataChildren = (_a = doc.descendantWithPath(`body.nav.ol`)) == null ? void 0 : _a.children;
120
+ } else if (doc.descendantWithPath(`body.section.nav.ol`)) {
121
+ navDataChildren = (_b = doc.descendantWithPath(`body.section.nav.ol`)) == null ? void 0 : _b.children;
122
+ }
123
+ if (navDataChildren && navDataChildren.length > 0) {
124
+ navDataChildren.filter((li) => li.name === `li`).forEach((li) => toc.push(extractNavChapter(li, { opfBasePath, baseUrl })));
125
+ }
126
+ return toc;
127
+ };
128
+ const parseTocFromNavPath = async (opfXmlDoc, archive, { opfBasePath, baseUrl }) => {
129
+ var _a;
130
+ const navItem = (_a = opfXmlDoc.childNamed(`manifest`)) == null ? void 0 : _a.childrenNamed(`item`).find((child) => child.attr.properties === `nav`);
131
+ if (navItem) {
132
+ const tocFile = Object.values(archive.files).find((item) => item.uri.endsWith(navItem.attr.href || ``));
133
+ if (tocFile) {
134
+ const doc = new xmldoc.XmlDocument(await tocFile.string());
135
+ return buildTOCFromNav(doc, { opfBasePath, baseUrl });
136
+ }
137
+ }
138
+ };
139
+ const mapNcxChapter = (point, { opfBasePath, baseUrl, prefix }) => {
140
+ var _a, _b;
141
+ const src = ((_a = point == null ? void 0 : point.childNamed(`${prefix}content`)) == null ? void 0 : _a.attr.src) || ``;
142
+ const out = {
143
+ title: ((_b = point == null ? void 0 : point.descendantWithPath(`${prefix}navLabel.${prefix}text`)) == null ? void 0 : _b.val) || ``,
144
+ path: urlJoin(opfBasePath, src),
145
+ href: urlJoin(baseUrl, opfBasePath, src),
41
146
  contents: []
42
- }, o = e.childrenNamed(`${a}navPoint`);
43
- return o && o.length > 0 && (r.contents = o.map((p) => X(p, { opfBasePath: i, baseUrl: n, prefix: a }))), r;
44
- }, Y = (e, { opfBasePath: i, baseUrl: n }) => {
45
- var o;
46
- const a = [], t = e.name;
47
- let r = "";
48
- return t.indexOf(":") !== -1 && (r = t.split(":")[0] + ":"), (o = e.childNamed(`${r}navMap`)) == null || o.childrenNamed(`${r}navPoint`).forEach((s) => a.push(X(s, { opfBasePath: i, baseUrl: n, prefix: r }))), a;
49
- }, Q = async ({
50
- opfData: e,
51
- opfBasePath: i,
52
- baseUrl: n,
53
- archive: a
147
+ };
148
+ const children = point.childrenNamed(`${prefix}navPoint`);
149
+ if (children && children.length > 0) {
150
+ out.contents = children.map((pt) => mapNcxChapter(pt, { opfBasePath, baseUrl, prefix }));
151
+ }
152
+ return out;
153
+ };
154
+ const buildTOCFromNCX = (ncxData, { opfBasePath, baseUrl }) => {
155
+ var _a;
156
+ const toc = [];
157
+ const rootTagName = ncxData.name;
158
+ let prefix = ``;
159
+ if (rootTagName.indexOf(`:`) !== -1) {
160
+ prefix = rootTagName.split(`:`)[0] + `:`;
161
+ }
162
+ (_a = ncxData.childNamed(`${prefix}navMap`)) == null ? void 0 : _a.childrenNamed(`${prefix}navPoint`).forEach((point) => toc.push(mapNcxChapter(point, { opfBasePath, baseUrl, prefix })));
163
+ return toc;
164
+ };
165
+ const parseTocFromNcx = async ({
166
+ opfData,
167
+ opfBasePath,
168
+ baseUrl,
169
+ archive
54
170
  }) => {
55
- var o;
56
- const t = e.childNamed("spine"), r = t && t.attr.toc;
57
- if (r) {
58
- const s = (o = e.childNamed("manifest")) == null ? void 0 : o.childrenNamed("item").find((d) => d.attr.id === r);
59
- if (s) {
60
- const d = `${i}${i === "" ? "" : "/"}${s.attr.href}`, p = Object.values(a.files).find((m) => m.uri.endsWith(d));
61
- if (p) {
62
- const m = new h.XmlDocument(await p.string());
63
- return Y(m, { opfBasePath: i, baseUrl: n });
171
+ var _a;
172
+ const spine = opfData.childNamed(`spine`);
173
+ const ncxId = spine && spine.attr.toc;
174
+ if (ncxId) {
175
+ const ncxItem = (_a = opfData.childNamed(`manifest`)) == null ? void 0 : _a.childrenNamed(`item`).find((item) => item.attr.id === ncxId);
176
+ if (ncxItem) {
177
+ const ncxPath = `${opfBasePath}${opfBasePath === `` ? `` : `/`}${ncxItem.attr.href}`;
178
+ const file = Object.values(archive.files).find((item) => item.uri.endsWith(ncxPath));
179
+ if (file) {
180
+ const ncxData = new xmldoc.XmlDocument(await file.string());
181
+ return buildTOCFromNCX(ncxData, { opfBasePath, baseUrl });
64
182
  }
65
183
  }
66
184
  }
67
- }, Z = async (e, i, { baseUrl: n }) => {
68
- const { basePath: a } = $(i) || {}, t = await Q({
69
- opfData: e,
70
- opfBasePath: a,
71
- archive: i,
72
- baseUrl: n
185
+ };
186
+ const parseToc = async (opfXmlDoc, archive, { baseUrl }) => {
187
+ const { basePath: opfBasePath } = getArchiveOpfInfo(archive) || {};
188
+ const tocFromNcx = await parseTocFromNcx({
189
+ opfData: opfXmlDoc,
190
+ opfBasePath,
191
+ archive,
192
+ baseUrl
73
193
  });
74
- return t || await K(e, i, { opfBasePath: a, baseUrl: n });
75
- }, E = async (e) => {
76
- const i = {
194
+ if (tocFromNcx) {
195
+ return tocFromNcx;
196
+ }
197
+ return await parseTocFromNavPath(opfXmlDoc, archive, { opfBasePath, baseUrl });
198
+ };
199
+ const extractKoboInformationFromArchive = async (archive) => {
200
+ const koboInformation = {
77
201
  renditionLayout: void 0
78
202
  };
79
- return await Promise.all(
80
- e.files.map(async (n) => {
81
- var a, t;
82
- if (n.uri.endsWith("com.kobobooks.display-options.xml")) {
83
- const o = (a = new h.XmlDocument(await n.string()).childNamed("platform")) == null ? void 0 : a.childNamed("option");
84
- ((t = o == null ? void 0 : o.attr) == null ? void 0 : t.name) === "fixed-layout" && o.val === "true" && (i.renditionLayout = "pre-paginated");
203
+ await Promise.all(
204
+ archive.files.map(async (file) => {
205
+ var _a, _b;
206
+ if (file.uri.endsWith(`com.kobobooks.display-options.xml`)) {
207
+ const opfXmlDoc = new xmldoc.XmlDocument(await file.string());
208
+ const optionElement = (_a = opfXmlDoc.childNamed(`platform`)) == null ? void 0 : _a.childNamed(`option`);
209
+ if (((_b = optionElement == null ? void 0 : optionElement.attr) == null ? void 0 : _b.name) === `fixed-layout` && optionElement.val === `true`) {
210
+ koboInformation.renditionLayout = `pre-paginated`;
211
+ }
85
212
  }
86
213
  })
87
- ), i;
214
+ );
215
+ return koboInformation;
88
216
  };
89
- let b = !1;
90
- const y = {
91
- enable: (e) => {
92
- b = e;
93
- },
94
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
95
- log: (...e) => {
96
- b && console.log("[prose-reader-streamer]", ...e);
97
- },
98
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
99
- warn: (...e) => {
100
- b && console.warn("[prose-reader-streamer]", ...e);
101
- },
102
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
103
- error: (...e) => {
104
- console.error(...e);
105
- },
106
- time: (e) => {
107
- b && console.time(`[prose-reader-streamer] [metric] ${e}`);
108
- },
109
- timeEnd: (e) => {
110
- b && console.timeEnd(`[prose-reader-streamer] [metric] ${e}`);
111
- },
112
- metric: (e, i = 1 / 0) => {
113
- const n = typeof e == "number" ? e : e.duration;
114
- b && (e.duration <= i ? console.log("[prose-reader-streamer] [metric] ", `${e.name} took ${n}ms`) : console.warn(
115
- "[prose-reader-streamer] [metric] ",
116
- `${e.name} took ${e.duration}ms which is above the ${i}ms target for this function`
117
- ));
118
- },
119
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
120
- measurePerformance: (e, i = 10, n) => (...a) => {
121
- const t = performance.now(), r = n(...a);
122
- if (r && r.then)
123
- return r.then((s) => {
124
- const d = performance.now();
125
- return y.metric({ name: e, duration: d - t }, i), s;
126
- });
127
- const o = performance.now();
128
- return y.metric({ name: e, duration: o - t }, i), r;
129
- }
130
- }, $ = (e) => {
131
- const n = Object.values(e.files).filter((a) => !a.dir).find((a) => a.uri.endsWith(".opf"));
132
- return {
133
- data: n,
134
- basePath: (n == null ? void 0 : n.uri.substring(0, n.uri.lastIndexOf("/"))) || ""
135
- };
136
- }, j = async ({ archive: e }) => {
137
- const { data: i, basePath: n } = $(e) || {}, a = await (i == null ? void 0 : i.string());
138
- if (!a)
217
+ const getSpineItemFilesFromArchive = async ({ archive }) => {
218
+ const { data: opsFile, basePath: opfBasePath } = getArchiveOpfInfo(archive) || {};
219
+ const data = await (opsFile == null ? void 0 : opsFile.string());
220
+ if (!data)
139
221
  return [];
140
- const t = new h.XmlDocument(a), r = t.childNamed("manifest"), o = t.childNamed("spine"), s = o == null ? void 0 : o.childrenNamed("itemref").map((m) => m.attr.idref), d = (r == null ? void 0 : r.childrenNamed("item").filter((m) => s.includes(m.attr.id || ""))) || [];
141
- return e.files.filter((m) => d.find((f) => n ? `${n}/${f.attr.href}` === m.uri : `${f.attr.href}` === m.uri));
142
- }, R = (e) => {
143
- var n;
144
- const i = e.childNamed("manifest");
145
- return ((n = i == null ? void 0 : i.childrenNamed("item")) == null ? void 0 : n.map((a) => ({
146
- href: a.attr.href || "",
147
- id: a.attr.id || "",
148
- mediaType: a.attr["media-type"]
222
+ const _opfXmlDoc = new xmldoc.XmlDocument(data);
223
+ const manifestElm = _opfXmlDoc.childNamed(`manifest`);
224
+ const spineElm = _opfXmlDoc.childNamed(`spine`);
225
+ const spineItemIds = spineElm == null ? void 0 : spineElm.childrenNamed(`itemref`).map((item) => item.attr.idref);
226
+ const manifestItemsFromSpine = (manifestElm == null ? void 0 : manifestElm.childrenNamed(`item`).filter((item) => spineItemIds.includes(item.attr.id || ``))) || [];
227
+ const archiveSpineItems = archive.files.filter((file) => {
228
+ return manifestItemsFromSpine.find((item) => {
229
+ if (!opfBasePath)
230
+ return `${item.attr.href}` === file.uri;
231
+ return `${opfBasePath}/${item.attr.href}` === file.uri;
232
+ });
233
+ });
234
+ return archiveSpineItems;
235
+ };
236
+ const getItemsFromDoc = (doc) => {
237
+ var _a;
238
+ const manifestElm = doc.childNamed(`manifest`);
239
+ return ((_a = manifestElm == null ? void 0 : manifestElm.childrenNamed(`item`)) == null ? void 0 : _a.map((el) => ({
240
+ href: el.attr.href || ``,
241
+ id: el.attr.id || ``,
242
+ mediaType: el.attr[`media-type`]
149
243
  }))) || [];
150
- }, ee = ({ archive: e, baseUrl: i }) => async (n) => {
151
- var A;
152
- const { data: a, basePath: t } = $(e) || {}, r = await E(e);
153
- if (!a)
154
- return n;
155
- const o = await a.string();
156
- y.log(o, r);
157
- const s = new h.XmlDocument(o), d = await Z(s, e, { baseUrl: i }) || [], p = s.childNamed("metadata"), m = s.childNamed("manifest"), f = s.childNamed("spine"), F = s.childNamed("guide"), w = p == null ? void 0 : p.childNamed("dc:title"), x = (p == null ? void 0 : p.childrenNamed("meta")) || [], N = x.find((l) => l.attr.property === "rendition:layout"), T = x.find((l) => l.attr.property === "rendition:flow"), I = x.find((l) => l.attr.property === "rendition:spread"), k = N == null ? void 0 : N.val, B = T == null ? void 0 : T.val, M = I == null ? void 0 : I.val, H = (w == null ? void 0 : w.val) || ((A = e.files.find(({ dir: l }) => l)) == null ? void 0 : A.basename) || "", U = f == null ? void 0 : f.attr["page-progression-direction"], V = (await j({ archive: e })).reduce((l, c) => c.size + l, 0);
244
+ };
245
+ const epubHook = ({ archive, baseUrl }) => async (manifest) => {
246
+ var _a;
247
+ const { data: opsFile, basePath: opfBasePath } = getArchiveOpfInfo(archive) || {};
248
+ const koboInformation = await extractKoboInformationFromArchive(archive);
249
+ if (!opsFile) {
250
+ return manifest;
251
+ }
252
+ const data = await opsFile.string();
253
+ Report.log(data, koboInformation);
254
+ const opfXmlDoc = new xmldoc.XmlDocument(data);
255
+ const toc = await parseToc(opfXmlDoc, archive, { baseUrl }) || [];
256
+ const metadataElm = opfXmlDoc.childNamed(`metadata`);
257
+ const manifestElm = opfXmlDoc.childNamed(`manifest`);
258
+ const spineElm = opfXmlDoc.childNamed(`spine`);
259
+ const guideElm = opfXmlDoc.childNamed(`guide`);
260
+ const titleElm = metadataElm == null ? void 0 : metadataElm.childNamed(`dc:title`);
261
+ const metaElmChildren = (metadataElm == null ? void 0 : metadataElm.childrenNamed(`meta`)) || [];
262
+ const metaElmWithRendition = metaElmChildren.find((meta) => meta.attr.property === `rendition:layout`);
263
+ const metaElmWithRenditionFlow = metaElmChildren.find((meta) => meta.attr.property === `rendition:flow`);
264
+ const metaElmWithRenditionSpread = metaElmChildren.find((meta) => meta.attr.property === `rendition:spread`);
265
+ const publisherRenditionLayout = metaElmWithRendition == null ? void 0 : metaElmWithRendition.val;
266
+ const publisherRenditionFlow = metaElmWithRenditionFlow == null ? void 0 : metaElmWithRenditionFlow.val;
267
+ const renditionSpread = metaElmWithRenditionSpread == null ? void 0 : metaElmWithRenditionSpread.val;
268
+ const title = (titleElm == null ? void 0 : titleElm.val) || ((_a = archive.files.find(({ dir }) => dir)) == null ? void 0 : _a.basename) || ``;
269
+ const pageProgressionDirection = spineElm == null ? void 0 : spineElm.attr[`page-progression-direction`];
270
+ const archiveSpineItems = await getSpineItemFilesFromArchive({ archive });
271
+ const totalSize = archiveSpineItems.reduce((size, file) => file.size + size, 0);
158
272
  return {
159
- filename: e.filename,
273
+ filename: archive.filename,
160
274
  nav: {
161
- toc: d
275
+ toc
162
276
  },
163
- renditionLayout: k || r.renditionLayout || "reflowable",
164
- renditionFlow: B || "auto",
165
- renditionSpread: M,
166
- title: H,
167
- readingDirection: U || "ltr",
168
- spineItems: (f == null ? void 0 : f.childrenNamed("itemref").map((l) => {
169
- var S, W, P;
170
- const c = m == null ? void 0 : m.childrenNamed("item").find((u) => u.attr.id === (l == null ? void 0 : l.attr.idref)), _ = (c == null ? void 0 : c.attr.href) || "", D = ((S = l == null ? void 0 : l.attr.properties) == null ? void 0 : S.split(" ")) || [], q = ((W = e.files.find((u) => u.uri.endsWith(_))) == null ? void 0 : W.size) || 0, C = i ?? "";
277
+ renditionLayout: publisherRenditionLayout || koboInformation.renditionLayout || `reflowable`,
278
+ renditionFlow: publisherRenditionFlow || `auto`,
279
+ renditionSpread,
280
+ title,
281
+ readingDirection: pageProgressionDirection || `ltr`,
282
+ spineItems: (spineElm == null ? void 0 : spineElm.childrenNamed(`itemref`).map((itemrefElm) => {
283
+ var _a2, _b, _c;
284
+ const manifestItem = manifestElm == null ? void 0 : manifestElm.childrenNamed(`item`).find((item) => item.attr.id === (itemrefElm == null ? void 0 : itemrefElm.attr.idref));
285
+ const href = (manifestItem == null ? void 0 : manifestItem.attr.href) || ``;
286
+ const properties = ((_a2 = itemrefElm == null ? void 0 : itemrefElm.attr.properties) == null ? void 0 : _a2.split(` `)) || [];
287
+ const itemSize = ((_b = archive.files.find((file) => file.uri.endsWith(href))) == null ? void 0 : _b.size) || 0;
288
+ const hrefBaseUri = baseUrl ?? "";
171
289
  return {
172
- id: (c == null ? void 0 : c.attr.id) || "",
173
- href: (P = c == null ? void 0 : c.attr.href) != null && P.startsWith("https://") ? c == null ? void 0 : c.attr.href : t ? `${C}${t}/${c == null ? void 0 : c.attr.href}` : `${C}${c == null ? void 0 : c.attr.href}`,
174
- renditionLayout: k || "reflowable",
175
- ...D.find((u) => u === "rendition:layout-reflowable") && {
176
- renditionLayout: "reflowable"
290
+ id: (manifestItem == null ? void 0 : manifestItem.attr.id) || ``,
291
+ href: ((_c = manifestItem == null ? void 0 : manifestItem.attr.href) == null ? void 0 : _c.startsWith(`https://`)) ? manifestItem == null ? void 0 : manifestItem.attr.href : opfBasePath ? `${hrefBaseUri}${opfBasePath}/${manifestItem == null ? void 0 : manifestItem.attr.href}` : `${hrefBaseUri}${manifestItem == null ? void 0 : manifestItem.attr.href}`,
292
+ renditionLayout: publisherRenditionLayout || `reflowable`,
293
+ ...properties.find((property) => property === `rendition:layout-reflowable`) && {
294
+ renditionLayout: `reflowable`
177
295
  },
178
- progressionWeight: q / V,
179
- pageSpreadLeft: D.some((u) => u === "page-spread-left") || void 0,
180
- pageSpreadRight: D.some((u) => u === "page-spread-right") || void 0,
296
+ progressionWeight: itemSize / totalSize,
297
+ pageSpreadLeft: properties.some((property) => property === `page-spread-left`) || void 0,
298
+ pageSpreadRight: properties.some((property) => property === `page-spread-right`) || void 0,
181
299
  // size: itemSize
182
- mediaType: c == null ? void 0 : c.attr["media-type"]
300
+ mediaType: manifestItem == null ? void 0 : manifestItem.attr[`media-type`]
183
301
  };
184
302
  })) || [],
185
- items: R(s),
186
- guide: F == null ? void 0 : F.childrenNamed("reference").map((l) => ({
187
- href: l.attr.href || "",
188
- title: l.attr.title || "",
189
- type: l.attr.type
190
- }))
303
+ items: getItemsFromDoc(opfXmlDoc),
304
+ guide: guideElm == null ? void 0 : guideElm.childrenNamed(`reference`).map((elm) => {
305
+ return {
306
+ href: elm.attr.href || ``,
307
+ title: elm.attr.title || ``,
308
+ type: elm.attr.type
309
+ };
310
+ })
311
+ };
312
+ };
313
+ const getMetadata = async (archive, resourcePath) => {
314
+ var _a, _b;
315
+ const opfInfo = getArchiveOpfInfo(archive);
316
+ const data = await ((_a = opfInfo.data) == null ? void 0 : _a.string());
317
+ if (data) {
318
+ const opfXmlDoc = new xmldoc.XmlDocument(data);
319
+ const items = getItemsFromDoc(opfXmlDoc);
320
+ return {
321
+ mediaType: (_b = items.find((item) => resourcePath.endsWith(item.href))) == null ? void 0 : _b.mediaType
322
+ };
323
+ }
324
+ return {
325
+ mediaType: getContentTypeFromExtension(resourcePath)
191
326
  };
192
- }, ue = async (e, i) => {
193
- const n = Object.values(e.files).find((r) => r.uri === i), a = await te(e, i);
194
- if (!n)
195
- throw new Error("no file found");
196
- const t = await n.blob();
327
+ };
328
+ const getContentTypeFromExtension = (uri) => {
329
+ if (uri.endsWith(`.css`)) {
330
+ return `text/css; charset=UTF-8`;
331
+ }
332
+ if (uri.endsWith(`.jpg`)) {
333
+ return `image/jpg`;
334
+ }
335
+ if (uri.endsWith(`.xhtml`)) {
336
+ return `application/xhtml+xml`;
337
+ }
338
+ if (uri.endsWith(`.mp4`)) {
339
+ return `video/mp4`;
340
+ }
341
+ if (uri.endsWith(`.svg`)) {
342
+ return `image/svg+xml`;
343
+ }
344
+ };
345
+ const defaultHook$1 = ({ archive, resourcePath }) => async (resource) => {
346
+ const file = Object.values(archive.files).find((file2) => file2.uri === resourcePath);
347
+ if (!file)
348
+ return resource;
349
+ const metadata = await getMetadata(archive, resourcePath);
197
350
  return {
198
- body: t,
351
+ ...resource,
199
352
  params: {
353
+ ...resource.params,
354
+ status: 200,
200
355
  headers: {
201
- ...t.type && {
202
- "Content-Type": t.type
203
- },
204
- ...n.encodingFormat && {
205
- "Content-Type": n.encodingFormat
356
+ ...(file == null ? void 0 : file.encodingFormat) && {
357
+ "Content-Type": file.encodingFormat
206
358
  },
207
- ...a.mediaType && {
208
- "Content-Type": a.mediaType
359
+ ...metadata.mediaType && {
360
+ "Content-Type": metadata.mediaType
209
361
  }
210
- // 'Cache-Control': `no-cache, no-store, no-transform`
211
362
  }
212
363
  }
213
364
  };
214
- }, te = async (e, i) => {
215
- var t, r;
216
- const a = await ((t = $(e).data) == null ? void 0 : t.string());
217
- if (a) {
218
- const o = new h.XmlDocument(a);
365
+ };
366
+ const generateResourceFromArchive = async (archive, resourcePath) => {
367
+ const file = Object.values(archive.files).find((file2) => file2.uri === resourcePath);
368
+ if (!file) {
369
+ throw new Error(`no file found`);
370
+ }
371
+ const defaultResource = {
372
+ params: {
373
+ status: 200
374
+ }
375
+ };
376
+ const hooks = [defaultHook$1({ archive, resourcePath }), cssFixHook({ archive, resourcePath })];
377
+ try {
378
+ const resource = await hooks.reduce(async (manifest, gen) => {
379
+ return await gen(await manifest);
380
+ }, Promise.resolve(defaultResource));
381
+ Report.log("Generated resource", resourcePath, resource);
219
382
  return {
220
- mediaType: (r = R(o).find((d) => i.endsWith(d.href))) == null ? void 0 : r.mediaType
383
+ ...resource,
384
+ body: resource.body || await file.blob()
221
385
  };
386
+ } catch (e) {
387
+ Report.error(e);
388
+ throw e;
222
389
  }
390
+ };
391
+ const generateResourceFromError = (error) => {
223
392
  return {
224
- mediaType: ne(i)
393
+ body: `
394
+ <!DOCTYPE html>
395
+ <html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="en" lang="en">
396
+ <head>
397
+ <meta name="${PROSE_READER_RESOURCE_ERROR_INJECTED_META_NAME}" content="${String(error)}" />
398
+ </head>
399
+ <body>
400
+ <pre>${String(error)}</pre>
401
+ </body>
402
+ </html>
403
+ `,
404
+ params: {
405
+ status: 500,
406
+ headers: {
407
+ "Content-Type": "text/html;charset=UTF-8"
408
+ }
409
+ }
225
410
  };
226
- }, ne = (e) => {
227
- if (e.endsWith(".css"))
228
- return "text/css; charset=UTF-8";
229
- if (e.endsWith(".jpg"))
230
- return "image/jpg";
231
- if (e.endsWith(".xhtml"))
232
- return "application/xhtml+xml";
233
- if (e.endsWith(".mp4"))
234
- return "video/mp4";
235
- if (e.endsWith(".svg"))
236
- return "image/svg+xml";
237
- }, re = ({ archive: e, baseUrl: i }) => async () => {
238
- var a;
239
- const n = Object.values(e.files).filter((t) => !t.dir);
411
+ };
412
+ const defaultHook = ({ archive, baseUrl }) => async () => {
413
+ var _a;
414
+ const files = Object.values(archive.files).filter((file) => !file.dir);
240
415
  return {
241
- filename: e.filename,
242
- title: ((a = e.files.find(({ dir: t }) => t)) == null ? void 0 : a.basename.replace(/\/$/, "")) || "",
243
- renditionLayout: "pre-paginated",
244
- renditionSpread: "auto",
245
- readingDirection: "ltr",
246
- spineItems: n.map((t, r) => ({
416
+ filename: archive.filename,
417
+ title: ((_a = archive.files.find(({ dir }) => dir)) == null ? void 0 : _a.basename.replace(/\/$/, ``)) || ``,
418
+ renditionLayout: `pre-paginated`,
419
+ renditionSpread: `auto`,
420
+ readingDirection: `ltr`,
421
+ spineItems: files.map((file, index) => ({
247
422
  // some books such as cbz can have same basename inside different sub folder
248
423
  // we need to make sure to have unique index
249
424
  // /chap01/01.png, /chap02/01.png, etc
250
- id: `${r}.${t.basename}`,
251
- href: encodeURI(`${i}${t.uri}`),
252
- renditionLayout: "pre-paginated",
253
- progressionWeight: 1 / n.length,
425
+ id: `${index}.${file.basename}`,
426
+ href: encodeURI(`${baseUrl}${file.uri}`),
427
+ renditionLayout: `pre-paginated`,
428
+ progressionWeight: 1 / files.length,
254
429
  pageSpreadLeft: void 0,
255
430
  pageSpreadRight: void 0,
256
- mediaType: t.encodingFormat
431
+ mediaType: file.encodingFormat
257
432
  })),
258
- items: n.map((t, r) => ({
259
- id: `${r}.${t.basename}`,
260
- href: `${i}${t.uri}`
433
+ items: files.map((file, index) => ({
434
+ id: `${index}.${file.basename}`,
435
+ href: `${baseUrl}${file.uri}`
261
436
  }))
262
437
  };
263
- }, ae = ({ archive: e, baseUrl: i }) => async (n) => {
264
- var s;
265
- const a = e.files.find((d) => d.basename.toLowerCase() === "comicinfo.xml");
266
- if (!a)
267
- return n;
268
- const t = await a.string(), o = ((s = new h.XmlDocument(t).childNamed("Manga")) == null ? void 0 : s.val) || "unknown";
438
+ };
439
+ const comicInfoHook = ({ archive, baseUrl }) => async (manifest) => {
440
+ var _a;
441
+ const comicInfoFile = archive.files.find((file) => file.basename.toLowerCase() === `comicinfo.xml`);
442
+ if (!comicInfoFile) {
443
+ return manifest;
444
+ }
445
+ const content = await comicInfoFile.string();
446
+ const xmlDoc = new xmldoc.XmlDocument(content);
447
+ const mangaVal = ((_a = xmlDoc.childNamed(`Manga`)) == null ? void 0 : _a.val) || `unknown`;
269
448
  return {
270
- ...n,
271
- spineItems: n.spineItems.filter((d) => d.id.toLowerCase() !== "comicinfo.xml"),
272
- readingDirection: o === "YesAndRightToLeft" ? "rtl" : "ltr"
449
+ ...manifest,
450
+ spineItems: manifest.spineItems.filter((item) => item.id.toLowerCase() !== `comicinfo.xml`),
451
+ readingDirection: mangaVal === `YesAndRightToLeft` ? `rtl` : `ltr`
273
452
  };
274
- }, ie = (e) => {
275
- var n;
276
- const i = (n = e.descendantWithPath("head")) == null ? void 0 : n.childrenNamed("meta").find((a) => a.attr.name === "viewport");
277
- return !!(i && i.attr.name === "viewport");
278
- }, oe = (e) => e.reduce(async (i, n) => {
279
- if (!await i || !G({
280
- mimeType: n.encodingFormat,
281
- uri: n.uri
282
- }))
283
- return !1;
284
- const t = await n.string();
285
- return t ? ie(new h.XmlDocument(t)) : !1;
286
- }, Promise.resolve(!0)), se = ({ archive: e, baseUrl: i }) => async (n) => {
287
- if (n.renditionLayout === "reflowable" && n.spineItems.every((t) => t.renditionLayout === "reflowable")) {
288
- const t = await j({ archive: e });
289
- if (await oe(t))
453
+ };
454
+ const hasDocMetaViewport = (doc) => {
455
+ var _a;
456
+ const metaElm = (_a = doc.descendantWithPath("head")) == null ? void 0 : _a.childrenNamed("meta").find((node) => node.attr.name === "viewport");
457
+ return !!(metaElm && metaElm.attr.name === "viewport");
458
+ };
459
+ const allFilesHaveViewportMeta = (files) => files.reduce(async (result, current) => {
460
+ const _result = await result;
461
+ if (!_result)
462
+ return false;
463
+ if (!isXmlBasedMimeType({
464
+ mimeType: current.encodingFormat,
465
+ uri: current.uri
466
+ })) {
467
+ return false;
468
+ }
469
+ const file = await current.string();
470
+ if (!file)
471
+ return false;
472
+ return hasDocMetaViewport(new xmldoc.XmlDocument(file));
473
+ }, Promise.resolve(true));
474
+ const epubOptimizerHook = ({ archive, baseUrl }) => async (manifest) => {
475
+ const bookIsFullReflowable = manifest.renditionLayout === "reflowable" && manifest.spineItems.every((item) => item.renditionLayout === "reflowable");
476
+ if (bookIsFullReflowable) {
477
+ const files = await getSpineItemFilesFromArchive({ archive });
478
+ const hasAllViewport = await allFilesHaveViewportMeta(files);
479
+ if (hasAllViewport) {
290
480
  return {
291
- ...n,
292
- spineItems: n.spineItems.map((o) => ({
293
- ...o,
481
+ ...manifest,
482
+ spineItems: manifest.spineItems.map((item) => ({
483
+ ...item,
294
484
  renditionLayout: "pre-paginated"
295
485
  })),
296
486
  renditionLayout: "pre-paginated"
297
487
  };
488
+ }
489
+ }
490
+ return manifest;
491
+ };
492
+ const sortByTitleComparator = (a, b) => {
493
+ var _a;
494
+ const alist = a.split(/(\d+)/);
495
+ const blist = b.split(/(\d+)/);
496
+ for (let i = 0, len = alist.length; i < len; i++) {
497
+ if (alist[i] !== blist[i]) {
498
+ if ((_a = alist[i]) == null ? void 0 : _a.match(/\d/)) {
499
+ return +(alist[i] || ``) - +(blist[i] || ``);
500
+ } else {
501
+ return (alist[i] || ``).localeCompare(blist[i] || ``);
502
+ }
503
+ }
298
504
  }
299
- return n;
300
- }, L = (e, i) => {
301
- var t;
302
- const n = e.split(/(\d+)/), a = i.split(/(\d+)/);
303
- for (let r = 0, o = n.length; r < o; r++)
304
- if (n[r] !== a[r])
305
- return (t = n[r]) != null && t.match(/\d/) ? +(n[r] || "") - +(a[r] || "") : (n[r] || "").localeCompare(a[r] || "");
306
505
  return 1;
307
- }, ce = ({ archive: e, baseUrl: i }) => async (n) => {
308
- if (n.nav)
309
- return n;
310
- const a = [...e.files].sort((r, o) => L(r.uri, o.uri)), t = Object.values(a).reduce((r, o) => {
311
- const s = o.uri.split("/");
312
- return !o.dir && s.length > 1 && s.forEach((p, m) => {
313
- if (m === s.length - 1)
314
- return;
315
- r.find(({ title: w }) => w === p) || r.push({
316
- contents: [],
317
- href: v(i, encodeURI(o.uri)).replace(/\/$/, ""),
318
- path: o.uri.replace(/\/$/, ""),
319
- title: s[0] ?? ""
506
+ };
507
+ const navigationFallbackHook = ({ archive, baseUrl }) => async (manifest) => {
508
+ if (manifest.nav)
509
+ return manifest;
510
+ const filesSortedByAlpha = [...archive.files].sort((a, b) => sortByTitleComparator(a.uri, b.uri));
511
+ const toc = Object.values(filesSortedByAlpha).reduce((acc, file) => {
512
+ const parts = file.uri.split("/");
513
+ const isFileUnderFolder = !file.dir && parts.length > 1;
514
+ if (isFileUnderFolder) {
515
+ parts.forEach((part, level) => {
516
+ const partIsFileName = level === parts.length - 1;
517
+ if (partIsFileName)
518
+ return;
519
+ const existingTocItem = acc.find(({ title }) => title === part);
520
+ if (existingTocItem)
521
+ ;
522
+ else {
523
+ acc.push({
524
+ contents: [],
525
+ href: urlJoin(baseUrl, encodeURI(file.uri)).replace(/\/$/, ""),
526
+ path: file.uri.replace(/\/$/, ""),
527
+ title: parts[0] ?? ""
528
+ });
529
+ }
320
530
  });
321
- }), r;
531
+ }
532
+ return acc;
322
533
  }, []);
323
- return t.length === 0 ? n : {
324
- ...n,
534
+ if (toc.length === 0)
535
+ return manifest;
536
+ return {
537
+ ...manifest,
325
538
  nav: {
326
- toc: t
539
+ toc
327
540
  }
328
541
  };
329
- }, de = {
330
- filename: "",
542
+ };
543
+ const baseManifest = {
544
+ filename: ``,
331
545
  items: [],
332
546
  nav: {
333
547
  toc: []
334
548
  },
335
- readingDirection: "ltr",
336
- renditionLayout: "pre-paginated",
337
- renditionSpread: "auto",
549
+ readingDirection: `ltr`,
550
+ renditionLayout: `pre-paginated`,
551
+ renditionSpread: `auto`,
338
552
  spineItems: [],
339
- title: ""
340
- }, he = async (e, { baseUrl: i = "" } = {}) => {
341
- const n = [
342
- re({ archive: e, baseUrl: i }),
343
- ee({ archive: e, baseUrl: i }),
344
- se({ archive: e, baseUrl: i }),
345
- ae({ archive: e, baseUrl: i }),
346
- ce({ archive: e, baseUrl: i })
553
+ title: ``
554
+ };
555
+ const generateManifestFromArchive = async (archive, { baseUrl = `` } = {}) => {
556
+ const hooks = [
557
+ defaultHook({ archive, baseUrl }),
558
+ epubHook({ archive, baseUrl }),
559
+ epubOptimizerHook({ archive, baseUrl }),
560
+ comicInfoHook({ archive, baseUrl }),
561
+ navigationFallbackHook({ archive, baseUrl })
347
562
  ];
348
563
  try {
349
- const a = await n.reduce(async (t, r) => await r(await t), Promise.resolve(de));
350
- return y.log("Generated manifest", a), a;
351
- } catch (a) {
352
- throw y.error(a), a;
564
+ const manifest = await hooks.reduce(async (manifest2, gen) => {
565
+ return await gen(await manifest2);
566
+ }, Promise.resolve(baseManifest));
567
+ Report.log("Generated manifest", manifest);
568
+ return manifest;
569
+ } catch (e) {
570
+ Report.error(e);
571
+ throw e;
353
572
  }
354
- }, g = (e) => e.substring(e.lastIndexOf("/") + 1) || e, ge = async (e, i) => {
355
- const n = `
573
+ };
574
+ const getUriBasename = (uri) => uri.substring(uri.lastIndexOf(`/`) + 1) || uri;
575
+ const createArchiveFromUrls = async (urls, options) => {
576
+ const opfFileData = `
356
577
  <?xml version="1.0" encoding="UTF-8"?><package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="bookid">
357
578
  <metadata>
358
- <meta property="rendition:layout">${i != null && i.useRenditionFlow ? "reflowable" : "pre-paginated"}</meta>
359
- ${i != null && i.useRenditionFlow ? '<meta property="rendition:flow">scrolled-continuous</meta>' : ""}
579
+ <meta property="rendition:layout">${(options == null ? void 0 : options.useRenditionFlow) ? `reflowable` : `pre-paginated`}</meta>
580
+ ${(options == null ? void 0 : options.useRenditionFlow) ? `<meta property="rendition:flow">scrolled-continuous</meta>` : ``}
360
581
  </metadata>
361
582
  <manifest>
362
- ${e.map((r) => `<item id="${g(r)}" href="${r}" media-type="${z(r)}"/>`).join(`
583
+ ${urls.map((url) => `<item id="${getUriBasename(url)}" href="${url}" media-type="${detectMimeTypeFromName(url)}"/>`).join(`
363
584
  `)}
364
585
  </manifest>
365
586
  <spine>
366
- ${e.map((r) => `<itemref idref="${g(r)}" />`).join(`
587
+ ${urls.map((url) => `<itemref idref="${getUriBasename(url)}" />`).join(`
367
588
  `)}
368
589
  </spine>
369
590
  </package>
370
- `, a = e.map((r) => ({
371
- dir: !1,
372
- basename: g(r),
373
- encodingFormat: z(r),
374
- uri: r,
375
- size: 100 / e.length,
376
- base64: async () => "",
591
+ `;
592
+ const filesFromUrl = urls.map((url) => ({
593
+ dir: false,
594
+ basename: getUriBasename(url),
595
+ encodingFormat: detectMimeTypeFromName(url),
596
+ uri: url,
597
+ size: 100 / urls.length,
598
+ base64: async () => ``,
377
599
  blob: async () => new Blob(),
378
- string: async () => ""
600
+ string: async () => ``
379
601
  }));
602
+ const opfFile = {
603
+ dir: false,
604
+ basename: `content.opf`,
605
+ uri: `content.opf`,
606
+ size: 0,
607
+ base64: async () => opfFileData,
608
+ blob: async () => new Blob(),
609
+ string: async () => opfFileData
610
+ };
380
611
  return {
381
- filename: "",
382
- files: [{
383
- dir: !1,
384
- basename: "content.opf",
385
- uri: "content.opf",
386
- size: 0,
387
- base64: async () => n,
388
- blob: async () => new Blob(),
389
- string: async () => n
390
- }, ...a]
612
+ filename: ``,
613
+ files: [opfFile, ...filesFromUrl]
391
614
  };
392
- }, le = async (e) => new Promise((i) => {
393
- const n = new FileReader();
394
- n.readAsDataURL(e), n.onloadend = function() {
395
- const a = n.result;
396
- i(a);
615
+ };
616
+ const blobToBase64 = async (blob) => new Promise((resolve) => {
617
+ const reader = new FileReader();
618
+ reader.readAsDataURL(blob);
619
+ reader.onloadend = function() {
620
+ const base64data = reader.result;
621
+ resolve(base64data);
397
622
  };
398
- }), ye = async (e, {
399
- mimeType: i,
400
- direction: n
623
+ });
624
+ const createArchiveFromText = async (content, {
625
+ mimeType,
626
+ direction
401
627
  } = { mimeType: "text/plain" }) => {
402
- const a = `
628
+ const txtOpfContent = `
403
629
  <?xml version="1.0" encoding="UTF-8"?>
404
630
  <package xmlns="http://www.idpf.org/2007/opf" version="3.0" xml:lang="ja" prefix="rendition: http://www.idpf.org/vocab/rendition/#"
405
631
  unique-identifier="ootuya-id">
@@ -410,85 +636,110 @@ const y = {
410
636
  <manifest>
411
637
  <item id="p01" href="p01.txt" media-type="text/plain"/>
412
638
  </manifest>
413
- <spine page-progression-direction="${n ?? "ltr"}">
639
+ <spine page-progression-direction="${direction ?? `ltr`}">
414
640
  <itemref idref="p01" />
415
641
  </spine>
416
642
  </package>
417
643
  `;
418
- return {
419
- filename: "content.txt",
644
+ const archive = {
645
+ filename: `content.txt`,
420
646
  files: [
421
647
  {
422
- dir: !1,
423
- basename: g("generated.opf"),
424
- uri: "generated.opf",
425
- blob: async () => new Blob([a]),
426
- string: async () => a,
427
- base64: async () => btoa(a),
648
+ dir: false,
649
+ basename: getUriBasename(`generated.opf`),
650
+ uri: `generated.opf`,
651
+ blob: async () => new Blob([txtOpfContent]),
652
+ string: async () => txtOpfContent,
653
+ base64: async () => btoa(txtOpfContent),
428
654
  size: 0
429
655
  },
430
656
  {
431
- dir: !1,
432
- basename: g("p01.txt"),
433
- uri: "p01.txt",
434
- blob: async () => typeof e == "string" ? new Blob([e]) : e,
435
- string: async () => typeof e == "string" ? e : e.text(),
436
- base64: async () => typeof e == "string" ? btoa(e) : le(e),
437
- size: typeof e == "string" ? e.length : e.size,
438
- encodingFormat: i
657
+ dir: false,
658
+ basename: getUriBasename(`p01.txt`),
659
+ uri: `p01.txt`,
660
+ blob: async () => {
661
+ if (typeof content === `string`)
662
+ return new Blob([content]);
663
+ return content;
664
+ },
665
+ string: async () => {
666
+ if (typeof content === `string`)
667
+ return content;
668
+ return content.text();
669
+ },
670
+ base64: async () => {
671
+ if (typeof content === `string`)
672
+ return btoa(content);
673
+ return blobToBase64(content);
674
+ },
675
+ size: typeof content === `string` ? content.length : content.size,
676
+ encodingFormat: mimeType
439
677
  }
440
678
  ]
441
679
  };
442
- }, be = async (e, { orderByAlpha: i, name: n } = {}) => {
443
- let a = Object.values(e.files);
444
- i && (a = a.sort((r, o) => L(r.name, o.name)));
445
- const t = {
446
- filename: n || "",
447
- files: a.map((r) => ({
448
- dir: r.dir,
449
- basename: g(r.name),
450
- uri: r.name,
451
- blob: () => r.async("blob"),
452
- string: () => r.async("string"),
453
- base64: () => r.async("base64"),
454
- ...r.internalStream && {
455
- stream: r.internalStream
680
+ return archive;
681
+ };
682
+ const createArchiveFromJszip = async (jszip, { orderByAlpha, name } = {}) => {
683
+ let files = Object.values(jszip.files);
684
+ if (orderByAlpha) {
685
+ files = files.sort((a, b) => sortByTitleComparator(a.name, b.name));
686
+ }
687
+ const archive = {
688
+ filename: name || ``,
689
+ files: files.map((file) => ({
690
+ dir: file.dir,
691
+ basename: getUriBasename(file.name),
692
+ uri: file.name,
693
+ blob: () => file.async(`blob`),
694
+ string: () => file.async(`string`),
695
+ base64: () => file.async(`base64`),
696
+ ...file.internalStream && {
697
+ stream: file.internalStream
456
698
  },
457
699
  // this is private API
458
700
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
459
701
  // @ts-ignore
460
- size: r._data.uncompressedSize
702
+ size: file._data.uncompressedSize
461
703
  }))
462
704
  };
463
- return y.log("Generated archive", t), t;
464
- }, we = async (e, { orderByAlpha: i, name: n } = {}) => {
465
- let a = e;
466
- return i && (a = a.sort((t, r) => L(t.name, r.name))), {
467
- filename: n || "",
468
- files: a.map((t) => ({
469
- dir: t.isDir,
470
- basename: g(t.name),
471
- uri: t.name,
472
- blob: async () => new Blob([await t.data()]),
705
+ Report.log("Generated archive", archive);
706
+ return archive;
707
+ };
708
+ const createArchiveFromArrayBufferList = async (list, { orderByAlpha, name } = {}) => {
709
+ let files = list;
710
+ if (orderByAlpha) {
711
+ files = files.sort((a, b) => sortByTitleComparator(a.name, b.name));
712
+ }
713
+ return {
714
+ filename: name || ``,
715
+ files: files.map((file) => ({
716
+ dir: file.isDir,
717
+ basename: getUriBasename(file.name),
718
+ uri: file.name,
719
+ blob: async () => new Blob([await file.data()]),
473
720
  string: async () => {
474
- const r = await t.data();
475
- return String.fromCharCode.apply(null, Array.from(new Uint16Array(r)));
721
+ const data = await file.data();
722
+ return String.fromCharCode.apply(null, Array.from(new Uint16Array(data)));
723
+ },
724
+ base64: async () => {
725
+ return ``;
476
726
  },
477
- base64: async () => "",
478
- size: t.size
727
+ size: file.size
479
728
  }))
480
729
  };
481
- }, ve = ({ enableReport: e } = {}) => {
482
- y.enable(!!e);
730
+ };
731
+ const configure = ({ enableReport } = {}) => {
732
+ Report.enable(!!enableReport);
483
733
  };
484
734
  export {
485
- ve as configure,
486
- we as createArchiveFromArrayBufferList,
487
- be as createArchiveFromJszip,
488
- ye as createArchiveFromText,
489
- ge as createArchiveFromUrls,
490
- he as generateManifestFromArchive,
491
- ue as generateResourceFromArchive,
492
- $ as getArchiveOpfInfo
735
+ configure,
736
+ createArchiveFromArrayBufferList,
737
+ createArchiveFromJszip,
738
+ createArchiveFromText,
739
+ createArchiveFromUrls,
740
+ generateManifestFromArchive,
741
+ generateResourceFromArchive,
742
+ generateResourceFromError,
743
+ getArchiveOpfInfo
493
744
  };
494
745
  //# sourceMappingURL=prose-streamer.js.map