@prose-reader/enhancer-gallery 1.303.0 → 1.305.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,190 +1,146 @@
1
- import { waitForFrameLoad as x, DocumentRenderer as P, injectCSS as $ } from "@prose-reader/core";
2
- import { combineLatest as v, from as j, defaultIfEmpty as H, of as S, switchMap as C, Observable as M, filter as T, first as q } from "rxjs";
3
- const F = (e, t) => {
4
- try {
5
- t.width = e.width, t.height = e.height;
6
- const r = t.getContext("2d");
7
- r && r.drawImage(e, 0, 0);
8
- } catch (r) {
9
- console.warn(
10
- "Could not copy canvas content - possible tainted canvas or cross-origin issue",
11
- r
12
- );
13
- }
14
- }, W = [
15
- "img",
16
- "video",
17
- "audio",
18
- "source",
19
- "link",
20
- "script"
21
- ].join(","), B = () => {
22
- const e = /* @__PURE__ */ new Set();
23
- return {
24
- add: (t) => {
25
- e.add(t);
26
- },
27
- revokeAll: () => {
28
- e.forEach((t) => {
29
- URL.revokeObjectURL(t);
30
- }), e.clear();
31
- }
32
- };
33
- }, z = (e) => e.getAttribute("src") || e.getAttribute("href"), V = (e, t) => {
34
- e.hasAttribute("src") ? e.setAttribute("src", t) : e.hasAttribute("href") && e.setAttribute("href", t);
35
- }, Y = async (e, t, r) => {
36
- const o = await (await fetch(e)).blob(), n = t.defaultView?.URL.createObjectURL(o);
37
- if (n)
38
- return r.add(n), n;
39
- }, L = async (e, t, r) => {
40
- const s = Array.from(
41
- e.querySelectorAll(W)
42
- );
43
- await Promise.all(
44
- s.map(async (o) => {
45
- const n = z(o);
46
- if (!n?.startsWith("blob:")) return;
47
- let a;
48
- try {
49
- a = await Y(n, t, r);
50
- } catch (i) {
51
- console.error("Error copying snapshot blob asset:", i);
52
- return;
53
- }
54
- a && V(o, a);
55
- })
56
- );
57
- }, G = (e, t, r) => {
58
- const s = Array.from(e).map(
59
- (o, n) => {
60
- const a = t[n];
61
- return a ? x(S(a)).pipe(
62
- C(async () => {
63
- try {
64
- if (o.contentDocument && a.contentDocument) {
65
- const i = o.contentDocument.body.cloneNode(!0);
66
- a.contentDocument.body.replaceWith(i);
67
- const f = o.contentDocument.head, y = a.contentDocument.head;
68
- Array.from(
69
- f.querySelectorAll('style, link[rel="stylesheet"]')
70
- ).forEach((u) => {
71
- y.appendChild(u.cloneNode(!0));
72
- }), await L(
73
- a.contentDocument,
74
- a.contentDocument,
75
- r
76
- );
77
- }
78
- return !0;
79
- } catch (i) {
80
- return console.error("Error copying iframe content:", i), !1;
81
- }
82
- })
83
- ) : S(!0);
84
- }
85
- );
86
- return s.length === 0 ? S(!0) : v(s);
87
- }, K = (e, t) => {
88
- const r = e.querySelectorAll("canvas"), s = t.querySelectorAll("canvas");
89
- r.forEach((o, n) => {
90
- if (n < s.length) {
91
- const a = s[n];
92
- F(o, a);
93
- }
94
- });
1
+ import { DocumentRenderer as e, injectCSS as t, waitForFrameLoad as n } from "@prose-reader/core";
2
+ import { Observable as r, combineLatest as i, defaultIfEmpty as a, filter as o, first as s, from as c, of as l, switchMap as u } from "rxjs";
3
+ //#region src/utils/redrawCanvas.ts
4
+ var d = (e, t) => {
5
+ try {
6
+ t.width = e.width, t.height = e.height;
7
+ let n = t.getContext("2d");
8
+ n && n.drawImage(e, 0, 0);
9
+ } catch (e) {
10
+ console.warn("Could not copy canvas content - possible tainted canvas or cross-origin issue", e);
11
+ }
12
+ }, f = [
13
+ "img",
14
+ "video",
15
+ "audio",
16
+ "source",
17
+ "link",
18
+ "script"
19
+ ].join(","), p = () => {
20
+ let e = /* @__PURE__ */ new Set();
21
+ return {
22
+ add: (t) => {
23
+ e.add(t);
24
+ },
25
+ revokeAll: () => {
26
+ e.forEach((e) => {
27
+ URL.revokeObjectURL(e);
28
+ }), e.clear();
29
+ }
30
+ };
31
+ }, m = (e) => e.getAttribute("src") || e.getAttribute("href"), h = (e, t) => {
32
+ e.hasAttribute("src") ? e.setAttribute("src", t) : e.hasAttribute("href") && e.setAttribute("href", t);
33
+ }, g = async (e, t, n) => {
34
+ let r = await (await fetch(e)).blob(), i = t.defaultView?.URL.createObjectURL(r);
35
+ if (i) return n.add(i), i;
36
+ }, _ = async (e, t, n) => {
37
+ let r = Array.from(e.querySelectorAll(f));
38
+ await Promise.all(r.map(async (e) => {
39
+ let r = m(e);
40
+ if (!r?.startsWith("blob:")) return;
41
+ let i;
42
+ try {
43
+ i = await g(r, t, n);
44
+ } catch (e) {
45
+ console.error("Error copying snapshot blob asset:", e);
46
+ return;
47
+ }
48
+ i && h(e, i);
49
+ }));
50
+ }, v = (e, t, r) => {
51
+ let a = Array.from(e).map((e, i) => {
52
+ let a = t[i];
53
+ return a ? n(l(a)).pipe(u(async () => {
54
+ try {
55
+ if (e.contentDocument && a.contentDocument) {
56
+ let t = e.contentDocument.body.cloneNode(!0);
57
+ a.contentDocument.body.replaceWith(t);
58
+ let n = e.contentDocument.head, i = a.contentDocument.head;
59
+ Array.from(n.querySelectorAll("style, link[rel=\"stylesheet\"]")).forEach((e) => {
60
+ i.appendChild(e.cloneNode(!0));
61
+ }), await _(a.contentDocument, a.contentDocument, r);
62
+ }
63
+ return !0;
64
+ } catch (e) {
65
+ return console.error("Error copying iframe content:", e), !1;
66
+ }
67
+ })) : l(!0);
68
+ });
69
+ return a.length === 0 ? l(!0) : i(a);
70
+ }, y = (e, t) => {
71
+ let n = e.querySelectorAll("canvas"), r = t.querySelectorAll("canvas");
72
+ n.forEach((e, t) => {
73
+ if (t < r.length) {
74
+ let n = r[t];
75
+ d(e, n);
76
+ }
77
+ });
95
78
  };
96
- function J(e) {
97
- const t = B(), r = e.cloneNode(!0), s = e.querySelectorAll("iframe"), o = r.querySelectorAll("iframe");
98
- K(e, r);
99
- const n = v([
100
- j(
101
- L(
102
- r,
103
- e.ownerDocument,
104
- t
105
- )
106
- ),
107
- G(s, o, t)
108
- ]);
109
- return {
110
- clone: r,
111
- ready$: n.pipe(H(!0)),
112
- release: t.revokeAll
113
- };
79
+ function b(e) {
80
+ let t = p(), n = e.cloneNode(!0), r = e.querySelectorAll("iframe"), o = n.querySelectorAll("iframe");
81
+ return y(e, n), {
82
+ clone: n,
83
+ ready$: i([c(_(n, e.ownerDocument, t)), v(r, o, t)]).pipe(a(!0)),
84
+ release: t.revokeAll
85
+ };
114
86
  }
115
- const Q = "prose-reader-enhancer-gallery-snapshot", X = "prose-reader-enhancer-gallery-snapshot-mask", Z = "prose-reader-enhancer-gallery-snapshot-preview", ee = "prose-reader-enhancer-gallery-snapshot-frame", te = (e) => {
116
- const t = e.createElement("div");
117
- t.classList.add(Q), t.tabIndex = -1, t.setAttribute("aria-hidden", "true"), t.setAttribute("inert", "");
118
- const r = e.createElement("div");
119
- return r.classList.add(X), t.appendChild(r), t;
120
- }, re = (e) => {
121
- e.classList.add(Z), e.tabIndex = -1, e.setAttribute("aria-hidden", "true"), e.setAttribute("inert", ""), e.querySelectorAll("iframe").forEach((t) => {
122
- t.classList.add(ee), t.tabIndex = -1, t.setAttribute("aria-hidden", "true"), t.setAttribute("inert", "");
123
- });
87
+ //#endregion
88
+ //#region src/Snapshot.ts
89
+ var x = "prose-reader-enhancer-gallery-snapshot", S = "prose-reader-enhancer-gallery-snapshot-mask", C = "prose-reader-enhancer-gallery-snapshot-preview", w = "prose-reader-enhancer-gallery-snapshot-frame", T = (e) => {
90
+ let t = e.createElement("div");
91
+ t.classList.add(x), t.tabIndex = -1, t.setAttribute("aria-hidden", "true"), t.setAttribute("inert", "");
92
+ let n = e.createElement("div");
93
+ return n.classList.add(S), t.appendChild(n), t;
94
+ }, E = (e) => {
95
+ e.classList.add(C), e.tabIndex = -1, e.setAttribute("aria-hidden", "true"), e.setAttribute("inert", ""), e.querySelectorAll("iframe").forEach((e) => {
96
+ e.classList.add(w), e.tabIndex = -1, e.setAttribute("aria-hidden", "true"), e.setAttribute("inert", "");
97
+ });
98
+ }, D = class extends r {
99
+ constructor(t, n, r, i) {
100
+ super((a) => {
101
+ let c = r.ownerDocument, l = t.spine.spineItemsLoader.forceOpen([n]), d = !1, f = () => {}, p, m = () => {
102
+ d || (d = !0, l());
103
+ }, h = n.isReady$.pipe(o((e) => e), s(), u(() => {
104
+ p = T(c);
105
+ let o = t.viewport.value.pageSize, s = p, l = s?.children[0];
106
+ if (!s || !l) throw Error("No item element or content mask");
107
+ l.style.top = "0", l.style.left = "0";
108
+ let u = i, { height: d, width: m } = n.layoutInfo, h = n.numberOfPages, g = u.width / m * h, _ = u.height / d, v = Math.min(g, _), { clone: y, ready$: x, release: S } = b(n.element);
109
+ f = S, Array.from(y.children).forEach((t) => {
110
+ t.classList.contains(e.DOCUMENT_CONTAINER_CLASS_NAME) || t.remove();
111
+ }), y.style.left = "0", y.style.top = "0", y.style.position = "relative", E(y);
112
+ let C = o.width * v, w = o.height * v;
113
+ if (l.style.width = `${o.width}px`, l.style.height = `${o.height}px`, l.style.transformOrigin = "0 0", l.style.transform = `scale(${v})`, C < u.width) {
114
+ let e = (u.width - C) / 2;
115
+ l.style.left = `${e}px`;
116
+ }
117
+ if (w < u.height) {
118
+ let e = (u.height - w) / 2;
119
+ l.style.top = `${e}px`;
120
+ }
121
+ return r.appendChild(s), l.appendChild(y), a.next(s), x;
122
+ })).subscribe({
123
+ error: (e) => {
124
+ m(), a.error(e);
125
+ },
126
+ complete: () => {
127
+ m();
128
+ }
129
+ });
130
+ return () => {
131
+ h.unsubscribe(), m(), f(), p?.remove();
132
+ };
133
+ });
134
+ }
135
+ }, O = ".prose-reader-enhancer-gallery-snapshot{width:100%;height:100%;position:relative;overflow:hidden}.prose-reader-enhancer-gallery-snapshot-mask{width:100%;height:100%;position:absolute;top:0;left:0;overflow:hidden}.prose-reader-enhancer-gallery-snapshot-preview{position:relative;top:0;left:0}.prose-reader-enhancer-gallery-snapshot,.prose-reader-enhancer-gallery-snapshot-mask,.prose-reader-enhancer-gallery-snapshot-preview,.prose-reader-enhancer-gallery-snapshot-frame,.prose-reader-enhancer-gallery-snapshot iframe{pointer-events:none;-webkit-user-select:none;user-select:none}", k = "prose-reader-enhancer-gallery-snapshot-styles", A = (e) => (n) => {
136
+ let r = e(n);
137
+ return typeof document < "u" && !document.getElementById(k) && t(document, k, O), {
138
+ ...r,
139
+ __PROSE_READER_ENHANCER_GALLERY: !0,
140
+ gallery: { snapshot: (e, t, n) => new D(r, e, t, n) }
141
+ };
124
142
  };
125
- class ne extends M {
126
- constructor(t, r, s, o) {
127
- super((n) => {
128
- const a = s.ownerDocument, i = t.spine.spineItemsLoader.forceOpen([r]);
129
- let f = !1, y = () => {
130
- }, u;
131
- const g = () => {
132
- f || (f = !0, i());
133
- }, I = r.isReady$.pipe(
134
- T((l) => l),
135
- q(),
136
- C(() => {
137
- u = te(a);
138
- const l = t.viewport.value.pageSize, m = u, c = m?.children[0];
139
- if (!m || !c)
140
- throw new Error("No item element or content mask");
141
- c.style.top = "0", c.style.left = "0";
142
- const h = o, { height: R, width: O } = r.layoutInfo, _ = r.numberOfPages, k = h.width / O * _, D = h.height / R, A = Math.min(k, D), {
143
- clone: d,
144
- ready$: U,
145
- release: N
146
- } = J(r.element);
147
- y = N, Array.from(d.children).forEach((p) => {
148
- p.classList.contains(
149
- P.DOCUMENT_CONTAINER_CLASS_NAME
150
- ) || p.remove();
151
- }), d.style.left = "0", d.style.top = "0", d.style.position = "relative", re(d);
152
- const b = l.width * A, w = l.height * A;
153
- if (c.style.width = `${l.width}px`, c.style.height = `${l.height}px`, c.style.transformOrigin = "0 0", c.style.transform = `scale(${A})`, b < h.width) {
154
- const p = (h.width - b) / 2;
155
- c.style.left = `${p}px`;
156
- }
157
- if (w < h.height) {
158
- const p = (h.height - w) / 2;
159
- c.style.top = `${p}px`;
160
- }
161
- return s.appendChild(m), c.appendChild(d), n.next(m), U;
162
- })
163
- ).subscribe({
164
- error: (l) => {
165
- g(), n.error(l);
166
- },
167
- complete: () => {
168
- g();
169
- }
170
- });
171
- return () => {
172
- I.unsubscribe(), g(), y(), u?.remove();
173
- };
174
- });
175
- }
176
- }
177
- const oe = ".prose-reader-enhancer-gallery-snapshot{width:100%;height:100%;position:relative;overflow:hidden}.prose-reader-enhancer-gallery-snapshot-mask{width:100%;height:100%;position:absolute;top:0;left:0;overflow:hidden}.prose-reader-enhancer-gallery-snapshot-preview{position:relative;top:0;left:0}.prose-reader-enhancer-gallery-snapshot,.prose-reader-enhancer-gallery-snapshot-mask,.prose-reader-enhancer-gallery-snapshot-preview,.prose-reader-enhancer-gallery-snapshot-frame,.prose-reader-enhancer-gallery-snapshot iframe{pointer-events:none;user-select:none;-webkit-user-select:none}", E = "prose-reader-enhancer-gallery-snapshot-styles", ce = (e) => (t) => {
178
- const r = e(t);
179
- return typeof document < "u" && !document.getElementById(E) && $(document, E, oe), {
180
- ...r,
181
- __PROSE_READER_ENHANCER_GALLERY: !0,
182
- gallery: {
183
- snapshot: (s, o, n) => new ne(r, s, o, n)
184
- }
185
- };
186
- };
187
- export {
188
- ce as galleryEnhancer
189
- };
190
- //# sourceMappingURL=index.js.map
143
+ //#endregion
144
+ export { A as galleryEnhancer };
145
+
146
+ //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/utils/redrawCanvas.ts","../src/utils/snapshotBlobAssets.ts","../src/utils/deepCloneElement.ts","../src/Snapshot.ts","../src/index.ts"],"sourcesContent":["export const redrawCanvas = (\n originalCanvas: HTMLCanvasElement,\n clonedCanvas: HTMLCanvasElement,\n) => {\n try {\n // Copy canvas dimensions\n clonedCanvas.width = originalCanvas.width\n clonedCanvas.height = originalCanvas.height\n\n // Copy canvas content\n const context = clonedCanvas.getContext(\"2d\")\n if (context) {\n context.drawImage(originalCanvas, 0, 0)\n }\n } catch (e) {\n console.warn(\n \"Could not copy canvas content - possible tainted canvas or cross-origin issue\",\n e,\n )\n }\n}\n","type SnapshotObjectUrlStore = {\n add: (url: string) => void\n revokeAll: () => void\n}\n\nconst RESOURCE_SELECTOR = [\n `img`,\n `video`,\n `audio`,\n `source`,\n `link`,\n `script`,\n].join(`,`)\n\nexport const createSnapshotObjectUrlStore = (): SnapshotObjectUrlStore => {\n const objectUrls = new Set<string>()\n\n return {\n add: (url) => {\n objectUrls.add(url)\n },\n revokeAll: () => {\n objectUrls.forEach((url) => {\n URL.revokeObjectURL(url)\n })\n objectUrls.clear()\n },\n }\n}\n\nconst getElementAssetUrl = (element: Element) =>\n element.getAttribute(`src`) || element.getAttribute(`href`)\n\nconst setElementAssetUrl = (element: Element, url: string) => {\n if (element.hasAttribute(`src`)) {\n element.setAttribute(`src`, url)\n } else if (element.hasAttribute(`href`)) {\n element.setAttribute(`href`, url)\n }\n}\n\nconst copyBlobUrl = async (\n url: string,\n document: Document,\n objectUrlStore: SnapshotObjectUrlStore,\n) => {\n const response = await fetch(url)\n const blob = await response.blob()\n const objectUrl = document.defaultView?.URL.createObjectURL(blob)\n\n if (!objectUrl) return\n\n objectUrlStore.add(objectUrl)\n\n return objectUrl\n}\n\nexport const copyBlobAssetReferences = async (\n root: ParentNode,\n document: Document,\n objectUrlStore: SnapshotObjectUrlStore,\n) => {\n const elementsWithAssets = Array.from(\n root.querySelectorAll(RESOURCE_SELECTOR),\n )\n\n await Promise.all(\n elementsWithAssets.map(async (element) => {\n const url = getElementAssetUrl(element)\n\n if (!url?.startsWith(`blob:`)) return\n\n let objectUrl: string | undefined\n\n try {\n objectUrl = await copyBlobUrl(url, document, objectUrlStore)\n } catch (error) {\n console.error(`Error copying snapshot blob asset:`, error)\n return\n }\n\n if (objectUrl) {\n setElementAssetUrl(element, objectUrl)\n }\n }),\n )\n}\n","import { waitForFrameLoad } from \"@prose-reader/core\"\nimport { combineLatest, defaultIfEmpty, from, of, switchMap } from \"rxjs\"\nimport { redrawCanvas } from \"./redrawCanvas\"\nimport {\n copyBlobAssetReferences,\n createSnapshotObjectUrlStore,\n} from \"./snapshotBlobAssets\"\n\nconst copyIframeContents = (\n originalIframes: NodeListOf<HTMLIFrameElement>,\n clonedIframes: NodeListOf<HTMLIFrameElement>,\n objectUrlStore: ReturnType<typeof createSnapshotObjectUrlStore>,\n) => {\n const iframeCopies = Array.from(originalIframes).map(\n (originalIframe, index) => {\n const clonedIframe = clonedIframes[index]\n\n if (!clonedIframe) return of(true)\n\n return waitForFrameLoad(of(clonedIframe)).pipe(\n switchMap(async () => {\n try {\n // Since we know they're same-origin EPUBs, we can directly copy content\n if (\n originalIframe.contentDocument &&\n clonedIframe.contentDocument\n ) {\n // Clone the entire body content\n const clonedBody =\n originalIframe.contentDocument.body.cloneNode(true)\n\n // Replace the body in the cloned iframe\n clonedIframe.contentDocument.body.replaceWith(clonedBody)\n\n // Also copy any head styles that might be important for rendering\n const originalHead = originalIframe.contentDocument.head\n const clonedHead = clonedIframe.contentDocument.head\n\n // Copy all style and link elements from head\n Array.from(\n originalHead.querySelectorAll('style, link[rel=\"stylesheet\"]'),\n ).forEach((node) => {\n clonedHead.appendChild(node.cloneNode(true))\n })\n\n await copyBlobAssetReferences(\n clonedIframe.contentDocument,\n clonedIframe.contentDocument,\n objectUrlStore,\n )\n }\n return true\n } catch (e) {\n console.error(\"Error copying iframe content:\", e)\n return false\n }\n }),\n )\n },\n )\n\n if (iframeCopies.length === 0) return of(true)\n\n return combineLatest(iframeCopies)\n}\n\nconst redrawCanvases = (sourceElement: HTMLElement, clone: HTMLElement) => {\n const originalCanvases = sourceElement.querySelectorAll(\"canvas\")\n const clonedCanvases = clone.querySelectorAll(\"canvas\")\n\n originalCanvases.forEach((originalCanvas, index) => {\n if (index < clonedCanvases.length) {\n const clonedCanvas = clonedCanvases[index] as HTMLCanvasElement\n\n redrawCanvas(originalCanvas, clonedCanvas)\n }\n })\n}\n\nexport function deepCloneElement(sourceElement: HTMLElement) {\n const objectUrlStore = createSnapshotObjectUrlStore()\n // Create a deep clone of the source element\n const clone = sourceElement.cloneNode(true) as HTMLElement\n\n // Find all iframes in the original element\n const originalIframes = sourceElement.querySelectorAll(\"iframe\")\n // Find all iframes in the cloned element\n const clonedIframes = clone.querySelectorAll(\"iframe\")\n\n // Handle canvases in the main document\n redrawCanvases(sourceElement, clone)\n\n const copyContents$ = combineLatest([\n from(\n copyBlobAssetReferences(\n clone,\n sourceElement.ownerDocument,\n objectUrlStore,\n ),\n ),\n copyIframeContents(originalIframes, clonedIframes, objectUrlStore),\n ])\n\n return {\n clone,\n ready$: copyContents$.pipe(defaultIfEmpty(true)),\n release: objectUrlStore.revokeAll,\n }\n}\n","import {\n DocumentRenderer,\n type Reader,\n type SpineItem,\n} from \"@prose-reader/core\"\nimport { filter, first, Observable, switchMap } from \"rxjs\"\nimport { deepCloneElement } from \"./utils/deepCloneElement\"\n\nconst SNAPSHOT_CLASS = \"prose-reader-enhancer-gallery-snapshot\"\nconst SNAPSHOT_MASK_CLASS = \"prose-reader-enhancer-gallery-snapshot-mask\"\nconst SNAPSHOT_PREVIEW_CLASS = \"prose-reader-enhancer-gallery-snapshot-preview\"\nconst SNAPSHOT_FRAME_CLASS = \"prose-reader-enhancer-gallery-snapshot-frame\"\n\nconst createSnapshotItem = (doc: Document) => {\n const spineItemContainerElement = doc.createElement(\"div\")\n spineItemContainerElement.classList.add(SNAPSHOT_CLASS)\n spineItemContainerElement.tabIndex = -1\n spineItemContainerElement.setAttribute(\"aria-hidden\", \"true\")\n spineItemContainerElement.setAttribute(\"inert\", \"\")\n\n const contentMask = doc.createElement(\"div\")\n\n contentMask.classList.add(SNAPSHOT_MASK_CLASS)\n\n spineItemContainerElement.appendChild(contentMask)\n\n return spineItemContainerElement\n}\n\nconst makeSnapshotPreviewInert = (element: HTMLElement) => {\n element.classList.add(SNAPSHOT_PREVIEW_CLASS)\n element.tabIndex = -1\n element.setAttribute(\"aria-hidden\", \"true\")\n element.setAttribute(\"inert\", \"\")\n\n element.querySelectorAll(\"iframe\").forEach((iframe) => {\n iframe.classList.add(SNAPSHOT_FRAME_CLASS)\n iframe.tabIndex = -1\n iframe.setAttribute(\"aria-hidden\", \"true\")\n iframe.setAttribute(\"inert\", \"\")\n })\n}\n\nexport class Snapshot extends Observable<HTMLElement> {\n constructor(\n reader: Reader,\n item: SpineItem,\n parent: Element,\n options: {\n height: number\n width: number\n },\n ) {\n super((subscriber) => {\n const parentDocument = parent.ownerDocument\n const unlockSpineItem = reader.spine.spineItemsLoader.forceOpen([item])\n let hasUnlockedSpineItem = false\n let releaseSnapshotAssets = () => {}\n let snapshotItem: HTMLElement | undefined\n\n const unlock = () => {\n if (hasUnlockedSpineItem) return\n\n hasUnlockedSpineItem = true\n unlockSpineItem()\n }\n\n const subscription = item.isReady$\n .pipe(\n filter((isReady) => isReady),\n first(),\n switchMap(() => {\n snapshotItem = createSnapshotItem(parentDocument)\n\n const pageSize = reader.viewport.value.pageSize\n const itemElement = snapshotItem\n const contentMask = itemElement?.children[0] as\n | HTMLElement\n | undefined\n\n if (!itemElement || !contentMask)\n throw new Error(\"No item element or content mask\")\n\n contentMask.style.top = \"0\"\n contentMask.style.left = \"0\"\n\n const measure = options\n const { height, width } = item.layoutInfo\n const numberOfPages = item.numberOfPages\n const widthScaleFullFrame = (measure.width / width) * numberOfPages\n const heightScale = measure.height / height\n\n // Use the minimum scale to ensure the element fits within both dimensions\n const scale = Math.min(widthScaleFullFrame, heightScale)\n\n const {\n clone: clonedElement,\n ready$: cloneReady$,\n release,\n } = deepCloneElement(item.element)\n releaseSnapshotAssets = release\n\n // cleanup unwanted elements from the spine\n Array.from(clonedElement.children).forEach((child) => {\n if (\n !child.classList.contains(\n DocumentRenderer.DOCUMENT_CONTAINER_CLASS_NAME,\n )\n ) {\n child.remove()\n }\n })\n\n clonedElement.style.left = \"0\"\n clonedElement.style.top = \"0\"\n clonedElement.style.position = \"relative\"\n makeSnapshotPreviewInert(clonedElement)\n\n /**\n * Now we adjust the mask to make it fit in the center and cover\n * only the required part of the spine item (hidding) the overflowing\n * pages for example.\n */\n const pageWidthAfterScale = pageSize.width * scale\n const pageHeightAfterScale = pageSize.height * scale\n\n contentMask.style.width = `${pageSize.width}px`\n contentMask.style.height = `${pageSize.height}px`\n contentMask.style.transformOrigin = \"0 0\"\n contentMask.style.transform = `scale(${scale})`\n\n if (pageWidthAfterScale < measure.width) {\n const gap = (measure.width - pageWidthAfterScale) / 2\n\n contentMask.style.left = `${gap}px`\n }\n\n if (pageHeightAfterScale < measure.height) {\n const gap = (measure.height - pageHeightAfterScale) / 2\n\n contentMask.style.top = `${gap}px`\n }\n\n parent.appendChild(itemElement)\n contentMask.appendChild(clonedElement)\n\n subscriber.next(itemElement)\n\n return cloneReady$\n }),\n )\n .subscribe({\n error: (error) => {\n unlock()\n subscriber.error(error)\n },\n complete: () => {\n unlock()\n // Keep the observable open after cloning so the thumbnail owns its\n // copied object URLs until React unsubscribes from this snapshot.\n },\n })\n\n return () => {\n subscription.unsubscribe()\n unlock()\n releaseSnapshotAssets()\n snapshotItem?.remove()\n }\n })\n }\n}\n","import { injectCSS, type Reader } from \"@prose-reader/core\"\nimport { Snapshot } from \"./Snapshot\"\nimport styles from \"./style.css?inline\"\nimport type { GalleryEnhancerAPI } from \"./types\"\n\nexport type { GalleryEnhancerAPI }\n\nconst STYLE_ID = \"prose-reader-enhancer-gallery-snapshot-styles\"\n\nexport const galleryEnhancer =\n <InheritOptions, InheritOutput extends Reader>(\n next: (options: InheritOptions) => InheritOutput,\n ) =>\n (options: InheritOptions): InheritOutput & GalleryEnhancerAPI => {\n const reader = next(options)\n\n if (typeof document !== \"undefined\" && !document.getElementById(STYLE_ID)) {\n injectCSS(document, STYLE_ID, styles)\n }\n\n return {\n ...reader,\n __PROSE_READER_ENHANCER_GALLERY: true,\n gallery: {\n snapshot: (spineItem, parent, options) =>\n new Snapshot(reader, spineItem, parent, options),\n },\n }\n }\n"],"names":["redrawCanvas","originalCanvas","clonedCanvas","context","e","RESOURCE_SELECTOR","createSnapshotObjectUrlStore","objectUrls","url","getElementAssetUrl","element","setElementAssetUrl","copyBlobUrl","document","objectUrlStore","blob","objectUrl","copyBlobAssetReferences","root","elementsWithAssets","error","copyIframeContents","originalIframes","clonedIframes","iframeCopies","originalIframe","index","clonedIframe","waitForFrameLoad","of","switchMap","clonedBody","originalHead","clonedHead","node","combineLatest","redrawCanvases","sourceElement","clone","originalCanvases","clonedCanvases","deepCloneElement","copyContents$","from","defaultIfEmpty","SNAPSHOT_CLASS","SNAPSHOT_MASK_CLASS","SNAPSHOT_PREVIEW_CLASS","SNAPSHOT_FRAME_CLASS","createSnapshotItem","doc","spineItemContainerElement","contentMask","makeSnapshotPreviewInert","iframe","Snapshot","Observable","reader","item","parent","options","subscriber","parentDocument","unlockSpineItem","hasUnlockedSpineItem","releaseSnapshotAssets","snapshotItem","unlock","subscription","filter","isReady","first","pageSize","itemElement","measure","height","width","numberOfPages","widthScaleFullFrame","heightScale","scale","clonedElement","cloneReady$","release","child","DocumentRenderer","pageWidthAfterScale","pageHeightAfterScale","gap","STYLE_ID","galleryEnhancer","next","injectCSS","styles","spineItem"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/utils/redrawCanvas.ts","../src/utils/snapshotBlobAssets.ts","../src/utils/deepCloneElement.ts","../src/Snapshot.ts","../src/style.css?inline","../src/index.ts"],"sourcesContent":["export const redrawCanvas = (\n originalCanvas: HTMLCanvasElement,\n clonedCanvas: HTMLCanvasElement,\n) => {\n try {\n // Copy canvas dimensions\n clonedCanvas.width = originalCanvas.width\n clonedCanvas.height = originalCanvas.height\n\n // Copy canvas content\n const context = clonedCanvas.getContext(\"2d\")\n if (context) {\n context.drawImage(originalCanvas, 0, 0)\n }\n } catch (e) {\n console.warn(\n \"Could not copy canvas content - possible tainted canvas or cross-origin issue\",\n e,\n )\n }\n}\n","type SnapshotObjectUrlStore = {\n add: (url: string) => void\n revokeAll: () => void\n}\n\nconst RESOURCE_SELECTOR = [\n `img`,\n `video`,\n `audio`,\n `source`,\n `link`,\n `script`,\n].join(`,`)\n\nexport const createSnapshotObjectUrlStore = (): SnapshotObjectUrlStore => {\n const objectUrls = new Set<string>()\n\n return {\n add: (url) => {\n objectUrls.add(url)\n },\n revokeAll: () => {\n objectUrls.forEach((url) => {\n URL.revokeObjectURL(url)\n })\n objectUrls.clear()\n },\n }\n}\n\nconst getElementAssetUrl = (element: Element) =>\n element.getAttribute(`src`) || element.getAttribute(`href`)\n\nconst setElementAssetUrl = (element: Element, url: string) => {\n if (element.hasAttribute(`src`)) {\n element.setAttribute(`src`, url)\n } else if (element.hasAttribute(`href`)) {\n element.setAttribute(`href`, url)\n }\n}\n\nconst copyBlobUrl = async (\n url: string,\n document: Document,\n objectUrlStore: SnapshotObjectUrlStore,\n) => {\n const response = await fetch(url)\n const blob = await response.blob()\n const objectUrl = document.defaultView?.URL.createObjectURL(blob)\n\n if (!objectUrl) return\n\n objectUrlStore.add(objectUrl)\n\n return objectUrl\n}\n\nexport const copyBlobAssetReferences = async (\n root: ParentNode,\n document: Document,\n objectUrlStore: SnapshotObjectUrlStore,\n) => {\n const elementsWithAssets = Array.from(\n root.querySelectorAll(RESOURCE_SELECTOR),\n )\n\n await Promise.all(\n elementsWithAssets.map(async (element) => {\n const url = getElementAssetUrl(element)\n\n if (!url?.startsWith(`blob:`)) return\n\n let objectUrl: string | undefined\n\n try {\n objectUrl = await copyBlobUrl(url, document, objectUrlStore)\n } catch (error) {\n console.error(`Error copying snapshot blob asset:`, error)\n return\n }\n\n if (objectUrl) {\n setElementAssetUrl(element, objectUrl)\n }\n }),\n )\n}\n","import { waitForFrameLoad } from \"@prose-reader/core\"\nimport { combineLatest, defaultIfEmpty, from, of, switchMap } from \"rxjs\"\nimport { redrawCanvas } from \"./redrawCanvas\"\nimport {\n copyBlobAssetReferences,\n createSnapshotObjectUrlStore,\n} from \"./snapshotBlobAssets\"\n\nconst copyIframeContents = (\n originalIframes: NodeListOf<HTMLIFrameElement>,\n clonedIframes: NodeListOf<HTMLIFrameElement>,\n objectUrlStore: ReturnType<typeof createSnapshotObjectUrlStore>,\n) => {\n const iframeCopies = Array.from(originalIframes).map(\n (originalIframe, index) => {\n const clonedIframe = clonedIframes[index]\n\n if (!clonedIframe) return of(true)\n\n return waitForFrameLoad(of(clonedIframe)).pipe(\n switchMap(async () => {\n try {\n // Since we know they're same-origin EPUBs, we can directly copy content\n if (\n originalIframe.contentDocument &&\n clonedIframe.contentDocument\n ) {\n // Clone the entire body content\n const clonedBody =\n originalIframe.contentDocument.body.cloneNode(true)\n\n // Replace the body in the cloned iframe\n clonedIframe.contentDocument.body.replaceWith(clonedBody)\n\n // Also copy any head styles that might be important for rendering\n const originalHead = originalIframe.contentDocument.head\n const clonedHead = clonedIframe.contentDocument.head\n\n // Copy all style and link elements from head\n Array.from(\n originalHead.querySelectorAll('style, link[rel=\"stylesheet\"]'),\n ).forEach((node) => {\n clonedHead.appendChild(node.cloneNode(true))\n })\n\n await copyBlobAssetReferences(\n clonedIframe.contentDocument,\n clonedIframe.contentDocument,\n objectUrlStore,\n )\n }\n return true\n } catch (e) {\n console.error(\"Error copying iframe content:\", e)\n return false\n }\n }),\n )\n },\n )\n\n if (iframeCopies.length === 0) return of(true)\n\n return combineLatest(iframeCopies)\n}\n\nconst redrawCanvases = (sourceElement: HTMLElement, clone: HTMLElement) => {\n const originalCanvases = sourceElement.querySelectorAll(\"canvas\")\n const clonedCanvases = clone.querySelectorAll(\"canvas\")\n\n originalCanvases.forEach((originalCanvas, index) => {\n if (index < clonedCanvases.length) {\n const clonedCanvas = clonedCanvases[index] as HTMLCanvasElement\n\n redrawCanvas(originalCanvas, clonedCanvas)\n }\n })\n}\n\nexport function deepCloneElement(sourceElement: HTMLElement) {\n const objectUrlStore = createSnapshotObjectUrlStore()\n // Create a deep clone of the source element\n const clone = sourceElement.cloneNode(true) as HTMLElement\n\n // Find all iframes in the original element\n const originalIframes = sourceElement.querySelectorAll(\"iframe\")\n // Find all iframes in the cloned element\n const clonedIframes = clone.querySelectorAll(\"iframe\")\n\n // Handle canvases in the main document\n redrawCanvases(sourceElement, clone)\n\n const copyContents$ = combineLatest([\n from(\n copyBlobAssetReferences(\n clone,\n sourceElement.ownerDocument,\n objectUrlStore,\n ),\n ),\n copyIframeContents(originalIframes, clonedIframes, objectUrlStore),\n ])\n\n return {\n clone,\n ready$: copyContents$.pipe(defaultIfEmpty(true)),\n release: objectUrlStore.revokeAll,\n }\n}\n","import {\n DocumentRenderer,\n type Reader,\n type SpineItem,\n} from \"@prose-reader/core\"\nimport { filter, first, Observable, switchMap } from \"rxjs\"\nimport { deepCloneElement } from \"./utils/deepCloneElement\"\n\nconst SNAPSHOT_CLASS = \"prose-reader-enhancer-gallery-snapshot\"\nconst SNAPSHOT_MASK_CLASS = \"prose-reader-enhancer-gallery-snapshot-mask\"\nconst SNAPSHOT_PREVIEW_CLASS = \"prose-reader-enhancer-gallery-snapshot-preview\"\nconst SNAPSHOT_FRAME_CLASS = \"prose-reader-enhancer-gallery-snapshot-frame\"\n\nconst createSnapshotItem = (doc: Document) => {\n const spineItemContainerElement = doc.createElement(\"div\")\n spineItemContainerElement.classList.add(SNAPSHOT_CLASS)\n spineItemContainerElement.tabIndex = -1\n spineItemContainerElement.setAttribute(\"aria-hidden\", \"true\")\n spineItemContainerElement.setAttribute(\"inert\", \"\")\n\n const contentMask = doc.createElement(\"div\")\n\n contentMask.classList.add(SNAPSHOT_MASK_CLASS)\n\n spineItemContainerElement.appendChild(contentMask)\n\n return spineItemContainerElement\n}\n\nconst makeSnapshotPreviewInert = (element: HTMLElement) => {\n element.classList.add(SNAPSHOT_PREVIEW_CLASS)\n element.tabIndex = -1\n element.setAttribute(\"aria-hidden\", \"true\")\n element.setAttribute(\"inert\", \"\")\n\n element.querySelectorAll(\"iframe\").forEach((iframe) => {\n iframe.classList.add(SNAPSHOT_FRAME_CLASS)\n iframe.tabIndex = -1\n iframe.setAttribute(\"aria-hidden\", \"true\")\n iframe.setAttribute(\"inert\", \"\")\n })\n}\n\nexport class Snapshot extends Observable<HTMLElement> {\n constructor(\n reader: Reader,\n item: SpineItem,\n parent: Element,\n options: {\n height: number\n width: number\n },\n ) {\n super((subscriber) => {\n const parentDocument = parent.ownerDocument\n const unlockSpineItem = reader.spine.spineItemsLoader.forceOpen([item])\n let hasUnlockedSpineItem = false\n let releaseSnapshotAssets = () => {}\n let snapshotItem: HTMLElement | undefined\n\n const unlock = () => {\n if (hasUnlockedSpineItem) return\n\n hasUnlockedSpineItem = true\n unlockSpineItem()\n }\n\n const subscription = item.isReady$\n .pipe(\n filter((isReady) => isReady),\n first(),\n switchMap(() => {\n snapshotItem = createSnapshotItem(parentDocument)\n\n const pageSize = reader.viewport.value.pageSize\n const itemElement = snapshotItem\n const contentMask = itemElement?.children[0] as\n | HTMLElement\n | undefined\n\n if (!itemElement || !contentMask)\n throw new Error(\"No item element or content mask\")\n\n contentMask.style.top = \"0\"\n contentMask.style.left = \"0\"\n\n const measure = options\n const { height, width } = item.layoutInfo\n const numberOfPages = item.numberOfPages\n const widthScaleFullFrame = (measure.width / width) * numberOfPages\n const heightScale = measure.height / height\n\n // Use the minimum scale to ensure the element fits within both dimensions\n const scale = Math.min(widthScaleFullFrame, heightScale)\n\n const {\n clone: clonedElement,\n ready$: cloneReady$,\n release,\n } = deepCloneElement(item.element)\n releaseSnapshotAssets = release\n\n // cleanup unwanted elements from the spine\n Array.from(clonedElement.children).forEach((child) => {\n if (\n !child.classList.contains(\n DocumentRenderer.DOCUMENT_CONTAINER_CLASS_NAME,\n )\n ) {\n child.remove()\n }\n })\n\n clonedElement.style.left = \"0\"\n clonedElement.style.top = \"0\"\n clonedElement.style.position = \"relative\"\n makeSnapshotPreviewInert(clonedElement)\n\n /**\n * Now we adjust the mask to make it fit in the center and cover\n * only the required part of the spine item (hidding) the overflowing\n * pages for example.\n */\n const pageWidthAfterScale = pageSize.width * scale\n const pageHeightAfterScale = pageSize.height * scale\n\n contentMask.style.width = `${pageSize.width}px`\n contentMask.style.height = `${pageSize.height}px`\n contentMask.style.transformOrigin = \"0 0\"\n contentMask.style.transform = `scale(${scale})`\n\n if (pageWidthAfterScale < measure.width) {\n const gap = (measure.width - pageWidthAfterScale) / 2\n\n contentMask.style.left = `${gap}px`\n }\n\n if (pageHeightAfterScale < measure.height) {\n const gap = (measure.height - pageHeightAfterScale) / 2\n\n contentMask.style.top = `${gap}px`\n }\n\n parent.appendChild(itemElement)\n contentMask.appendChild(clonedElement)\n\n subscriber.next(itemElement)\n\n return cloneReady$\n }),\n )\n .subscribe({\n error: (error) => {\n unlock()\n subscriber.error(error)\n },\n complete: () => {\n unlock()\n // Keep the observable open after cloning so the thumbnail owns its\n // copied object URLs until React unsubscribes from this snapshot.\n },\n })\n\n return () => {\n subscription.unsubscribe()\n unlock()\n releaseSnapshotAssets()\n snapshotItem?.remove()\n }\n })\n }\n}\n",".prose-reader-enhancer-gallery-snapshot {\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.prose-reader-enhancer-gallery-snapshot-mask {\n width: 100%;\n height: 100%;\n position: absolute;\n top: 0;\n left: 0;\n overflow: hidden;\n}\n\n.prose-reader-enhancer-gallery-snapshot-preview {\n position: relative;\n top: 0;\n left: 0;\n}\n\n.prose-reader-enhancer-gallery-snapshot,\n.prose-reader-enhancer-gallery-snapshot-mask,\n.prose-reader-enhancer-gallery-snapshot-preview,\n.prose-reader-enhancer-gallery-snapshot-frame,\n.prose-reader-enhancer-gallery-snapshot iframe {\n pointer-events: none;\n user-select: none;\n -webkit-user-select: none;\n}\n","import { injectCSS, type Reader } from \"@prose-reader/core\"\nimport { Snapshot } from \"./Snapshot\"\nimport styles from \"./style.css?inline\"\nimport type { GalleryEnhancerAPI } from \"./types\"\n\nexport type { GalleryEnhancerAPI }\n\nconst STYLE_ID = \"prose-reader-enhancer-gallery-snapshot-styles\"\n\nexport const galleryEnhancer =\n <InheritOptions, InheritOutput extends Reader>(\n next: (options: InheritOptions) => InheritOutput,\n ) =>\n (options: InheritOptions): InheritOutput & GalleryEnhancerAPI => {\n const reader = next(options)\n\n if (typeof document !== \"undefined\" && !document.getElementById(STYLE_ID)) {\n injectCSS(document, STYLE_ID, styles)\n }\n\n return {\n ...reader,\n __PROSE_READER_ENHANCER_GALLERY: true,\n gallery: {\n snapshot: (spineItem, parent, options) =>\n new Snapshot(reader, spineItem, parent, options),\n },\n }\n }\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- (function(i,h){typeof exports=="object"&&typeof module<"u"?h(exports,require("@prose-reader/core"),require("rxjs")):typeof define=="function"&&define.amd?define(["exports","@prose-reader/core","rxjs"],h):(i=typeof globalThis<"u"?globalThis:i||self,h(i["prose-reader-enhancer-gallery"]={},i.core,i.rxjs))})(this,(function(i,h,c){"use strict";const I=(e,t)=>{try{t.width=e.width,t.height=e.height;const r=t.getContext("2d");r&&r.drawImage(e,0,0)}catch(r){console.warn("Could not copy canvas content - possible tainted canvas or cross-origin issue",r)}},R=["img","video","audio","source","link","script"].join(","),O=()=>{const e=new Set;return{add:t=>{e.add(t)},revokeAll:()=>{e.forEach(t=>{URL.revokeObjectURL(t)}),e.clear()}}},_=e=>e.getAttribute("src")||e.getAttribute("href"),k=(e,t)=>{e.hasAttribute("src")?e.setAttribute("src",t):e.hasAttribute("href")&&e.setAttribute("href",t)},D=async(e,t,r)=>{const o=await(await fetch(e)).blob(),n=t.defaultView?.URL.createObjectURL(o);if(n)return r.add(n),n},E=async(e,t,r)=>{const s=Array.from(e.querySelectorAll(R));await Promise.all(s.map(async o=>{const n=_(o);if(!n?.startsWith("blob:"))return;let a;try{a=await D(n,t,r)}catch(p){console.error("Error copying snapshot blob asset:",p);return}a&&k(o,a)}))},U=(e,t,r)=>{const s=Array.from(e).map((o,n)=>{const a=t[n];return a?h.waitForFrameLoad(c.of(a)).pipe(c.switchMap(async()=>{try{if(o.contentDocument&&a.contentDocument){const p=o.contentDocument.body.cloneNode(!0);a.contentDocument.body.replaceWith(p);const g=o.contentDocument.head,S=a.contentDocument.head;Array.from(g.querySelectorAll('style, link[rel="stylesheet"]')).forEach(m=>{S.appendChild(m.cloneNode(!0))}),await E(a.contentDocument,a.contentDocument,r)}return!0}catch(p){return console.error("Error copying iframe content:",p),!1}})):c.of(!0)});return s.length===0?c.of(!0):c.combineLatest(s)},N=(e,t)=>{const r=e.querySelectorAll("canvas"),s=t.querySelectorAll("canvas");r.forEach((o,n)=>{if(n<s.length){const a=s[n];I(o,a)}})};function P(e){const t=O(),r=e.cloneNode(!0),s=e.querySelectorAll("iframe"),o=r.querySelectorAll("iframe");N(e,r);const n=c.combineLatest([c.from(E(r,e.ownerDocument,t)),U(s,o,t)]);return{clone:r,ready$:n.pipe(c.defaultIfEmpty(!0)),release:t.revokeAll}}const T="prose-reader-enhancer-gallery-snapshot",M="prose-reader-enhancer-gallery-snapshot-mask",$="prose-reader-enhancer-gallery-snapshot-preview",q="prose-reader-enhancer-gallery-snapshot-frame",H=e=>{const t=e.createElement("div");t.classList.add(T),t.tabIndex=-1,t.setAttribute("aria-hidden","true"),t.setAttribute("inert","");const r=e.createElement("div");return r.classList.add(M),t.appendChild(r),t},F=e=>{e.classList.add($),e.tabIndex=-1,e.setAttribute("aria-hidden","true"),e.setAttribute("inert",""),e.querySelectorAll("iframe").forEach(t=>{t.classList.add(q),t.tabIndex=-1,t.setAttribute("aria-hidden","true"),t.setAttribute("inert","")})};class W extends c.Observable{constructor(t,r,s,o){super(n=>{const a=s.ownerDocument,p=t.spine.spineItemsLoader.forceOpen([r]);let g=!1,S=()=>{},m;const b=()=>{g||(g=!0,p())},j=r.isReady$.pipe(c.filter(d=>d),c.first(),c.switchMap(()=>{m=H(a);const d=t.viewport.value.pageSize,A=m,l=A?.children[0];if(!A||!l)throw new Error("No item element or content mask");l.style.top="0",l.style.left="0";const u=o,{height:z,width:V}=r.layoutInfo,Y=r.numberOfPages,G=u.width/V*Y,K=u.height/z,w=Math.min(G,K),{clone:f,ready$:J,release:Q}=P(r.element);S=Q,Array.from(f.children).forEach(y=>{y.classList.contains(h.DocumentRenderer.DOCUMENT_CONTAINER_CLASS_NAME)||y.remove()}),f.style.left="0",f.style.top="0",f.style.position="relative",F(f);const C=d.width*w,L=d.height*w;if(l.style.width=`${d.width}px`,l.style.height=`${d.height}px`,l.style.transformOrigin="0 0",l.style.transform=`scale(${w})`,C<u.width){const y=(u.width-C)/2;l.style.left=`${y}px`}if(L<u.height){const y=(u.height-L)/2;l.style.top=`${y}px`}return s.appendChild(A),l.appendChild(f),n.next(A),J})).subscribe({error:d=>{b(),n.error(d)},complete:()=>{b()}});return()=>{j.unsubscribe(),b(),S(),m?.remove()}})}}const x=".prose-reader-enhancer-gallery-snapshot{width:100%;height:100%;position:relative;overflow:hidden}.prose-reader-enhancer-gallery-snapshot-mask{width:100%;height:100%;position:absolute;top:0;left:0;overflow:hidden}.prose-reader-enhancer-gallery-snapshot-preview{position:relative;top:0;left:0}.prose-reader-enhancer-gallery-snapshot,.prose-reader-enhancer-gallery-snapshot-mask,.prose-reader-enhancer-gallery-snapshot-preview,.prose-reader-enhancer-gallery-snapshot-frame,.prose-reader-enhancer-gallery-snapshot iframe{pointer-events:none;user-select:none;-webkit-user-select:none}",v="prose-reader-enhancer-gallery-snapshot-styles",B=e=>t=>{const r=e(t);return typeof document<"u"&&!document.getElementById(v)&&h.injectCSS(document,v,x),{...r,__PROSE_READER_ENHANCER_GALLERY:!0,gallery:{snapshot:(s,o,n)=>new W(r,s,o,n)}}};i.galleryEnhancer=B,Object.defineProperty(i,Symbol.toStringTag,{value:"Module"})}));
2
- //# sourceMappingURL=index.umd.cjs.map
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("@prose-reader/core"),require("rxjs")):typeof define==`function`&&define.amd?define([`exports`,`@prose-reader/core`,`rxjs`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e[`prose-reader-enhancer-gallery`]={},e._prose_reader_core,e.rxjs))})(this,function(e,t,n){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var r=(e,t)=>{try{t.width=e.width,t.height=e.height;let n=t.getContext(`2d`);n&&n.drawImage(e,0,0)}catch(e){console.warn(`Could not copy canvas content - possible tainted canvas or cross-origin issue`,e)}},i=[`img`,`video`,`audio`,`source`,`link`,`script`].join(`,`),a=()=>{let e=new Set;return{add:t=>{e.add(t)},revokeAll:()=>{e.forEach(e=>{URL.revokeObjectURL(e)}),e.clear()}}},o=e=>e.getAttribute(`src`)||e.getAttribute(`href`),s=(e,t)=>{e.hasAttribute(`src`)?e.setAttribute(`src`,t):e.hasAttribute(`href`)&&e.setAttribute(`href`,t)},c=async(e,t,n)=>{let r=await(await fetch(e)).blob(),i=t.defaultView?.URL.createObjectURL(r);if(i)return n.add(i),i},l=async(e,t,n)=>{let r=Array.from(e.querySelectorAll(i));await Promise.all(r.map(async e=>{let r=o(e);if(!r?.startsWith(`blob:`))return;let i;try{i=await c(r,t,n)}catch(e){console.error(`Error copying snapshot blob asset:`,e);return}i&&s(e,i)}))},u=(e,r,i)=>{let a=Array.from(e).map((e,a)=>{let o=r[a];return o?(0,t.waitForFrameLoad)((0,n.of)(o)).pipe((0,n.switchMap)(async()=>{try{if(e.contentDocument&&o.contentDocument){let t=e.contentDocument.body.cloneNode(!0);o.contentDocument.body.replaceWith(t);let n=e.contentDocument.head,r=o.contentDocument.head;Array.from(n.querySelectorAll(`style, link[rel="stylesheet"]`)).forEach(e=>{r.appendChild(e.cloneNode(!0))}),await l(o.contentDocument,o.contentDocument,i)}return!0}catch(e){return console.error(`Error copying iframe content:`,e),!1}})):(0,n.of)(!0)});return a.length===0?(0,n.of)(!0):(0,n.combineLatest)(a)},d=(e,t)=>{let n=e.querySelectorAll(`canvas`),i=t.querySelectorAll(`canvas`);n.forEach((e,t)=>{if(t<i.length){let n=i[t];r(e,n)}})};function f(e){let t=a(),r=e.cloneNode(!0),i=e.querySelectorAll(`iframe`),o=r.querySelectorAll(`iframe`);return d(e,r),{clone:r,ready$:(0,n.combineLatest)([(0,n.from)(l(r,e.ownerDocument,t)),u(i,o,t)]).pipe((0,n.defaultIfEmpty)(!0)),release:t.revokeAll}}var p=`prose-reader-enhancer-gallery-snapshot`,m=`prose-reader-enhancer-gallery-snapshot-mask`,h=`prose-reader-enhancer-gallery-snapshot-preview`,g=`prose-reader-enhancer-gallery-snapshot-frame`,_=e=>{let t=e.createElement(`div`);t.classList.add(p),t.tabIndex=-1,t.setAttribute(`aria-hidden`,`true`),t.setAttribute(`inert`,``);let n=e.createElement(`div`);return n.classList.add(m),t.appendChild(n),t},v=e=>{e.classList.add(h),e.tabIndex=-1,e.setAttribute(`aria-hidden`,`true`),e.setAttribute(`inert`,``),e.querySelectorAll(`iframe`).forEach(e=>{e.classList.add(g),e.tabIndex=-1,e.setAttribute(`aria-hidden`,`true`),e.setAttribute(`inert`,``)})},y=class extends n.Observable{constructor(e,r,i,a){super(o=>{let s=i.ownerDocument,c=e.spine.spineItemsLoader.forceOpen([r]),l=!1,u=()=>{},d,p=()=>{l||(l=!0,c())},m=r.isReady$.pipe((0,n.filter)(e=>e),(0,n.first)(),(0,n.switchMap)(()=>{d=_(s);let n=e.viewport.value.pageSize,c=d,l=c?.children[0];if(!c||!l)throw Error(`No item element or content mask`);l.style.top=`0`,l.style.left=`0`;let p=a,{height:m,width:h}=r.layoutInfo,g=r.numberOfPages,y=p.width/h*g,b=p.height/m,x=Math.min(y,b),{clone:S,ready$:C,release:w}=f(r.element);u=w,Array.from(S.children).forEach(e=>{e.classList.contains(t.DocumentRenderer.DOCUMENT_CONTAINER_CLASS_NAME)||e.remove()}),S.style.left=`0`,S.style.top=`0`,S.style.position=`relative`,v(S);let T=n.width*x,E=n.height*x;if(l.style.width=`${n.width}px`,l.style.height=`${n.height}px`,l.style.transformOrigin=`0 0`,l.style.transform=`scale(${x})`,T<p.width){let e=(p.width-T)/2;l.style.left=`${e}px`}if(E<p.height){let e=(p.height-E)/2;l.style.top=`${e}px`}return i.appendChild(c),l.appendChild(S),o.next(c),C})).subscribe({error:e=>{p(),o.error(e)},complete:()=>{p()}});return()=>{m.unsubscribe(),p(),u(),d?.remove()}})}},b=`.prose-reader-enhancer-gallery-snapshot{width:100%;height:100%;position:relative;overflow:hidden}.prose-reader-enhancer-gallery-snapshot-mask{width:100%;height:100%;position:absolute;top:0;left:0;overflow:hidden}.prose-reader-enhancer-gallery-snapshot-preview{position:relative;top:0;left:0}.prose-reader-enhancer-gallery-snapshot,.prose-reader-enhancer-gallery-snapshot-mask,.prose-reader-enhancer-gallery-snapshot-preview,.prose-reader-enhancer-gallery-snapshot-frame,.prose-reader-enhancer-gallery-snapshot iframe{pointer-events:none;-webkit-user-select:none;user-select:none}`,x=`prose-reader-enhancer-gallery-snapshot-styles`;e.galleryEnhancer=e=>n=>{let r=e(n);return typeof document<`u`&&!document.getElementById(x)&&(0,t.injectCSS)(document,x,b),{...r,__PROSE_READER_ENHANCER_GALLERY:!0,gallery:{snapshot:(e,t,n)=>new y(r,e,t,n)}}}});
2
+ //# sourceMappingURL=index.umd.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.umd.cjs","sources":["../src/utils/redrawCanvas.ts","../src/utils/snapshotBlobAssets.ts","../src/utils/deepCloneElement.ts","../src/Snapshot.ts","../src/index.ts"],"sourcesContent":["export const redrawCanvas = (\n originalCanvas: HTMLCanvasElement,\n clonedCanvas: HTMLCanvasElement,\n) => {\n try {\n // Copy canvas dimensions\n clonedCanvas.width = originalCanvas.width\n clonedCanvas.height = originalCanvas.height\n\n // Copy canvas content\n const context = clonedCanvas.getContext(\"2d\")\n if (context) {\n context.drawImage(originalCanvas, 0, 0)\n }\n } catch (e) {\n console.warn(\n \"Could not copy canvas content - possible tainted canvas or cross-origin issue\",\n e,\n )\n }\n}\n","type SnapshotObjectUrlStore = {\n add: (url: string) => void\n revokeAll: () => void\n}\n\nconst RESOURCE_SELECTOR = [\n `img`,\n `video`,\n `audio`,\n `source`,\n `link`,\n `script`,\n].join(`,`)\n\nexport const createSnapshotObjectUrlStore = (): SnapshotObjectUrlStore => {\n const objectUrls = new Set<string>()\n\n return {\n add: (url) => {\n objectUrls.add(url)\n },\n revokeAll: () => {\n objectUrls.forEach((url) => {\n URL.revokeObjectURL(url)\n })\n objectUrls.clear()\n },\n }\n}\n\nconst getElementAssetUrl = (element: Element) =>\n element.getAttribute(`src`) || element.getAttribute(`href`)\n\nconst setElementAssetUrl = (element: Element, url: string) => {\n if (element.hasAttribute(`src`)) {\n element.setAttribute(`src`, url)\n } else if (element.hasAttribute(`href`)) {\n element.setAttribute(`href`, url)\n }\n}\n\nconst copyBlobUrl = async (\n url: string,\n document: Document,\n objectUrlStore: SnapshotObjectUrlStore,\n) => {\n const response = await fetch(url)\n const blob = await response.blob()\n const objectUrl = document.defaultView?.URL.createObjectURL(blob)\n\n if (!objectUrl) return\n\n objectUrlStore.add(objectUrl)\n\n return objectUrl\n}\n\nexport const copyBlobAssetReferences = async (\n root: ParentNode,\n document: Document,\n objectUrlStore: SnapshotObjectUrlStore,\n) => {\n const elementsWithAssets = Array.from(\n root.querySelectorAll(RESOURCE_SELECTOR),\n )\n\n await Promise.all(\n elementsWithAssets.map(async (element) => {\n const url = getElementAssetUrl(element)\n\n if (!url?.startsWith(`blob:`)) return\n\n let objectUrl: string | undefined\n\n try {\n objectUrl = await copyBlobUrl(url, document, objectUrlStore)\n } catch (error) {\n console.error(`Error copying snapshot blob asset:`, error)\n return\n }\n\n if (objectUrl) {\n setElementAssetUrl(element, objectUrl)\n }\n }),\n )\n}\n","import { waitForFrameLoad } from \"@prose-reader/core\"\nimport { combineLatest, defaultIfEmpty, from, of, switchMap } from \"rxjs\"\nimport { redrawCanvas } from \"./redrawCanvas\"\nimport {\n copyBlobAssetReferences,\n createSnapshotObjectUrlStore,\n} from \"./snapshotBlobAssets\"\n\nconst copyIframeContents = (\n originalIframes: NodeListOf<HTMLIFrameElement>,\n clonedIframes: NodeListOf<HTMLIFrameElement>,\n objectUrlStore: ReturnType<typeof createSnapshotObjectUrlStore>,\n) => {\n const iframeCopies = Array.from(originalIframes).map(\n (originalIframe, index) => {\n const clonedIframe = clonedIframes[index]\n\n if (!clonedIframe) return of(true)\n\n return waitForFrameLoad(of(clonedIframe)).pipe(\n switchMap(async () => {\n try {\n // Since we know they're same-origin EPUBs, we can directly copy content\n if (\n originalIframe.contentDocument &&\n clonedIframe.contentDocument\n ) {\n // Clone the entire body content\n const clonedBody =\n originalIframe.contentDocument.body.cloneNode(true)\n\n // Replace the body in the cloned iframe\n clonedIframe.contentDocument.body.replaceWith(clonedBody)\n\n // Also copy any head styles that might be important for rendering\n const originalHead = originalIframe.contentDocument.head\n const clonedHead = clonedIframe.contentDocument.head\n\n // Copy all style and link elements from head\n Array.from(\n originalHead.querySelectorAll('style, link[rel=\"stylesheet\"]'),\n ).forEach((node) => {\n clonedHead.appendChild(node.cloneNode(true))\n })\n\n await copyBlobAssetReferences(\n clonedIframe.contentDocument,\n clonedIframe.contentDocument,\n objectUrlStore,\n )\n }\n return true\n } catch (e) {\n console.error(\"Error copying iframe content:\", e)\n return false\n }\n }),\n )\n },\n )\n\n if (iframeCopies.length === 0) return of(true)\n\n return combineLatest(iframeCopies)\n}\n\nconst redrawCanvases = (sourceElement: HTMLElement, clone: HTMLElement) => {\n const originalCanvases = sourceElement.querySelectorAll(\"canvas\")\n const clonedCanvases = clone.querySelectorAll(\"canvas\")\n\n originalCanvases.forEach((originalCanvas, index) => {\n if (index < clonedCanvases.length) {\n const clonedCanvas = clonedCanvases[index] as HTMLCanvasElement\n\n redrawCanvas(originalCanvas, clonedCanvas)\n }\n })\n}\n\nexport function deepCloneElement(sourceElement: HTMLElement) {\n const objectUrlStore = createSnapshotObjectUrlStore()\n // Create a deep clone of the source element\n const clone = sourceElement.cloneNode(true) as HTMLElement\n\n // Find all iframes in the original element\n const originalIframes = sourceElement.querySelectorAll(\"iframe\")\n // Find all iframes in the cloned element\n const clonedIframes = clone.querySelectorAll(\"iframe\")\n\n // Handle canvases in the main document\n redrawCanvases(sourceElement, clone)\n\n const copyContents$ = combineLatest([\n from(\n copyBlobAssetReferences(\n clone,\n sourceElement.ownerDocument,\n objectUrlStore,\n ),\n ),\n copyIframeContents(originalIframes, clonedIframes, objectUrlStore),\n ])\n\n return {\n clone,\n ready$: copyContents$.pipe(defaultIfEmpty(true)),\n release: objectUrlStore.revokeAll,\n }\n}\n","import {\n DocumentRenderer,\n type Reader,\n type SpineItem,\n} from \"@prose-reader/core\"\nimport { filter, first, Observable, switchMap } from \"rxjs\"\nimport { deepCloneElement } from \"./utils/deepCloneElement\"\n\nconst SNAPSHOT_CLASS = \"prose-reader-enhancer-gallery-snapshot\"\nconst SNAPSHOT_MASK_CLASS = \"prose-reader-enhancer-gallery-snapshot-mask\"\nconst SNAPSHOT_PREVIEW_CLASS = \"prose-reader-enhancer-gallery-snapshot-preview\"\nconst SNAPSHOT_FRAME_CLASS = \"prose-reader-enhancer-gallery-snapshot-frame\"\n\nconst createSnapshotItem = (doc: Document) => {\n const spineItemContainerElement = doc.createElement(\"div\")\n spineItemContainerElement.classList.add(SNAPSHOT_CLASS)\n spineItemContainerElement.tabIndex = -1\n spineItemContainerElement.setAttribute(\"aria-hidden\", \"true\")\n spineItemContainerElement.setAttribute(\"inert\", \"\")\n\n const contentMask = doc.createElement(\"div\")\n\n contentMask.classList.add(SNAPSHOT_MASK_CLASS)\n\n spineItemContainerElement.appendChild(contentMask)\n\n return spineItemContainerElement\n}\n\nconst makeSnapshotPreviewInert = (element: HTMLElement) => {\n element.classList.add(SNAPSHOT_PREVIEW_CLASS)\n element.tabIndex = -1\n element.setAttribute(\"aria-hidden\", \"true\")\n element.setAttribute(\"inert\", \"\")\n\n element.querySelectorAll(\"iframe\").forEach((iframe) => {\n iframe.classList.add(SNAPSHOT_FRAME_CLASS)\n iframe.tabIndex = -1\n iframe.setAttribute(\"aria-hidden\", \"true\")\n iframe.setAttribute(\"inert\", \"\")\n })\n}\n\nexport class Snapshot extends Observable<HTMLElement> {\n constructor(\n reader: Reader,\n item: SpineItem,\n parent: Element,\n options: {\n height: number\n width: number\n },\n ) {\n super((subscriber) => {\n const parentDocument = parent.ownerDocument\n const unlockSpineItem = reader.spine.spineItemsLoader.forceOpen([item])\n let hasUnlockedSpineItem = false\n let releaseSnapshotAssets = () => {}\n let snapshotItem: HTMLElement | undefined\n\n const unlock = () => {\n if (hasUnlockedSpineItem) return\n\n hasUnlockedSpineItem = true\n unlockSpineItem()\n }\n\n const subscription = item.isReady$\n .pipe(\n filter((isReady) => isReady),\n first(),\n switchMap(() => {\n snapshotItem = createSnapshotItem(parentDocument)\n\n const pageSize = reader.viewport.value.pageSize\n const itemElement = snapshotItem\n const contentMask = itemElement?.children[0] as\n | HTMLElement\n | undefined\n\n if (!itemElement || !contentMask)\n throw new Error(\"No item element or content mask\")\n\n contentMask.style.top = \"0\"\n contentMask.style.left = \"0\"\n\n const measure = options\n const { height, width } = item.layoutInfo\n const numberOfPages = item.numberOfPages\n const widthScaleFullFrame = (measure.width / width) * numberOfPages\n const heightScale = measure.height / height\n\n // Use the minimum scale to ensure the element fits within both dimensions\n const scale = Math.min(widthScaleFullFrame, heightScale)\n\n const {\n clone: clonedElement,\n ready$: cloneReady$,\n release,\n } = deepCloneElement(item.element)\n releaseSnapshotAssets = release\n\n // cleanup unwanted elements from the spine\n Array.from(clonedElement.children).forEach((child) => {\n if (\n !child.classList.contains(\n DocumentRenderer.DOCUMENT_CONTAINER_CLASS_NAME,\n )\n ) {\n child.remove()\n }\n })\n\n clonedElement.style.left = \"0\"\n clonedElement.style.top = \"0\"\n clonedElement.style.position = \"relative\"\n makeSnapshotPreviewInert(clonedElement)\n\n /**\n * Now we adjust the mask to make it fit in the center and cover\n * only the required part of the spine item (hidding) the overflowing\n * pages for example.\n */\n const pageWidthAfterScale = pageSize.width * scale\n const pageHeightAfterScale = pageSize.height * scale\n\n contentMask.style.width = `${pageSize.width}px`\n contentMask.style.height = `${pageSize.height}px`\n contentMask.style.transformOrigin = \"0 0\"\n contentMask.style.transform = `scale(${scale})`\n\n if (pageWidthAfterScale < measure.width) {\n const gap = (measure.width - pageWidthAfterScale) / 2\n\n contentMask.style.left = `${gap}px`\n }\n\n if (pageHeightAfterScale < measure.height) {\n const gap = (measure.height - pageHeightAfterScale) / 2\n\n contentMask.style.top = `${gap}px`\n }\n\n parent.appendChild(itemElement)\n contentMask.appendChild(clonedElement)\n\n subscriber.next(itemElement)\n\n return cloneReady$\n }),\n )\n .subscribe({\n error: (error) => {\n unlock()\n subscriber.error(error)\n },\n complete: () => {\n unlock()\n // Keep the observable open after cloning so the thumbnail owns its\n // copied object URLs until React unsubscribes from this snapshot.\n },\n })\n\n return () => {\n subscription.unsubscribe()\n unlock()\n releaseSnapshotAssets()\n snapshotItem?.remove()\n }\n })\n }\n}\n","import { injectCSS, type Reader } from \"@prose-reader/core\"\nimport { Snapshot } from \"./Snapshot\"\nimport styles from \"./style.css?inline\"\nimport type { GalleryEnhancerAPI } from \"./types\"\n\nexport type { GalleryEnhancerAPI }\n\nconst STYLE_ID = \"prose-reader-enhancer-gallery-snapshot-styles\"\n\nexport const galleryEnhancer =\n <InheritOptions, InheritOutput extends Reader>(\n next: (options: InheritOptions) => InheritOutput,\n ) =>\n (options: InheritOptions): InheritOutput & GalleryEnhancerAPI => {\n const reader = next(options)\n\n if (typeof document !== \"undefined\" && !document.getElementById(STYLE_ID)) {\n injectCSS(document, STYLE_ID, styles)\n }\n\n return {\n ...reader,\n __PROSE_READER_ENHANCER_GALLERY: true,\n gallery: {\n snapshot: (spineItem, parent, options) =>\n new Snapshot(reader, spineItem, parent, options),\n },\n }\n }\n"],"names":["redrawCanvas","originalCanvas","clonedCanvas","context","e","RESOURCE_SELECTOR","createSnapshotObjectUrlStore","objectUrls","url","getElementAssetUrl","element","setElementAssetUrl","copyBlobUrl","document","objectUrlStore","blob","objectUrl","copyBlobAssetReferences","root","elementsWithAssets","error","copyIframeContents","originalIframes","clonedIframes","iframeCopies","originalIframe","index","clonedIframe","waitForFrameLoad","of","switchMap","clonedBody","originalHead","clonedHead","node","combineLatest","redrawCanvases","sourceElement","clone","originalCanvases","clonedCanvases","deepCloneElement","copyContents$","from","defaultIfEmpty","SNAPSHOT_CLASS","SNAPSHOT_MASK_CLASS","SNAPSHOT_PREVIEW_CLASS","SNAPSHOT_FRAME_CLASS","createSnapshotItem","doc","spineItemContainerElement","contentMask","makeSnapshotPreviewInert","iframe","Snapshot","Observable","reader","item","parent","options","subscriber","parentDocument","unlockSpineItem","hasUnlockedSpineItem","releaseSnapshotAssets","snapshotItem","unlock","subscription","filter","isReady","first","pageSize","itemElement","measure","height","width","numberOfPages","widthScaleFullFrame","heightScale","scale","clonedElement","cloneReady$","release","child","DocumentRenderer","pageWidthAfterScale","pageHeightAfterScale","gap","STYLE_ID","galleryEnhancer","next","injectCSS","styles","spineItem"],"mappings":"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"}
1
+ {"version":3,"file":"index.umd.cjs","names":[],"sources":["../src/utils/redrawCanvas.ts","../src/utils/snapshotBlobAssets.ts","../src/utils/deepCloneElement.ts","../src/Snapshot.ts","../src/style.css?inline","../src/index.ts"],"sourcesContent":["export const redrawCanvas = (\n originalCanvas: HTMLCanvasElement,\n clonedCanvas: HTMLCanvasElement,\n) => {\n try {\n // Copy canvas dimensions\n clonedCanvas.width = originalCanvas.width\n clonedCanvas.height = originalCanvas.height\n\n // Copy canvas content\n const context = clonedCanvas.getContext(\"2d\")\n if (context) {\n context.drawImage(originalCanvas, 0, 0)\n }\n } catch (e) {\n console.warn(\n \"Could not copy canvas content - possible tainted canvas or cross-origin issue\",\n e,\n )\n }\n}\n","type SnapshotObjectUrlStore = {\n add: (url: string) => void\n revokeAll: () => void\n}\n\nconst RESOURCE_SELECTOR = [\n `img`,\n `video`,\n `audio`,\n `source`,\n `link`,\n `script`,\n].join(`,`)\n\nexport const createSnapshotObjectUrlStore = (): SnapshotObjectUrlStore => {\n const objectUrls = new Set<string>()\n\n return {\n add: (url) => {\n objectUrls.add(url)\n },\n revokeAll: () => {\n objectUrls.forEach((url) => {\n URL.revokeObjectURL(url)\n })\n objectUrls.clear()\n },\n }\n}\n\nconst getElementAssetUrl = (element: Element) =>\n element.getAttribute(`src`) || element.getAttribute(`href`)\n\nconst setElementAssetUrl = (element: Element, url: string) => {\n if (element.hasAttribute(`src`)) {\n element.setAttribute(`src`, url)\n } else if (element.hasAttribute(`href`)) {\n element.setAttribute(`href`, url)\n }\n}\n\nconst copyBlobUrl = async (\n url: string,\n document: Document,\n objectUrlStore: SnapshotObjectUrlStore,\n) => {\n const response = await fetch(url)\n const blob = await response.blob()\n const objectUrl = document.defaultView?.URL.createObjectURL(blob)\n\n if (!objectUrl) return\n\n objectUrlStore.add(objectUrl)\n\n return objectUrl\n}\n\nexport const copyBlobAssetReferences = async (\n root: ParentNode,\n document: Document,\n objectUrlStore: SnapshotObjectUrlStore,\n) => {\n const elementsWithAssets = Array.from(\n root.querySelectorAll(RESOURCE_SELECTOR),\n )\n\n await Promise.all(\n elementsWithAssets.map(async (element) => {\n const url = getElementAssetUrl(element)\n\n if (!url?.startsWith(`blob:`)) return\n\n let objectUrl: string | undefined\n\n try {\n objectUrl = await copyBlobUrl(url, document, objectUrlStore)\n } catch (error) {\n console.error(`Error copying snapshot blob asset:`, error)\n return\n }\n\n if (objectUrl) {\n setElementAssetUrl(element, objectUrl)\n }\n }),\n )\n}\n","import { waitForFrameLoad } from \"@prose-reader/core\"\nimport { combineLatest, defaultIfEmpty, from, of, switchMap } from \"rxjs\"\nimport { redrawCanvas } from \"./redrawCanvas\"\nimport {\n copyBlobAssetReferences,\n createSnapshotObjectUrlStore,\n} from \"./snapshotBlobAssets\"\n\nconst copyIframeContents = (\n originalIframes: NodeListOf<HTMLIFrameElement>,\n clonedIframes: NodeListOf<HTMLIFrameElement>,\n objectUrlStore: ReturnType<typeof createSnapshotObjectUrlStore>,\n) => {\n const iframeCopies = Array.from(originalIframes).map(\n (originalIframe, index) => {\n const clonedIframe = clonedIframes[index]\n\n if (!clonedIframe) return of(true)\n\n return waitForFrameLoad(of(clonedIframe)).pipe(\n switchMap(async () => {\n try {\n // Since we know they're same-origin EPUBs, we can directly copy content\n if (\n originalIframe.contentDocument &&\n clonedIframe.contentDocument\n ) {\n // Clone the entire body content\n const clonedBody =\n originalIframe.contentDocument.body.cloneNode(true)\n\n // Replace the body in the cloned iframe\n clonedIframe.contentDocument.body.replaceWith(clonedBody)\n\n // Also copy any head styles that might be important for rendering\n const originalHead = originalIframe.contentDocument.head\n const clonedHead = clonedIframe.contentDocument.head\n\n // Copy all style and link elements from head\n Array.from(\n originalHead.querySelectorAll('style, link[rel=\"stylesheet\"]'),\n ).forEach((node) => {\n clonedHead.appendChild(node.cloneNode(true))\n })\n\n await copyBlobAssetReferences(\n clonedIframe.contentDocument,\n clonedIframe.contentDocument,\n objectUrlStore,\n )\n }\n return true\n } catch (e) {\n console.error(\"Error copying iframe content:\", e)\n return false\n }\n }),\n )\n },\n )\n\n if (iframeCopies.length === 0) return of(true)\n\n return combineLatest(iframeCopies)\n}\n\nconst redrawCanvases = (sourceElement: HTMLElement, clone: HTMLElement) => {\n const originalCanvases = sourceElement.querySelectorAll(\"canvas\")\n const clonedCanvases = clone.querySelectorAll(\"canvas\")\n\n originalCanvases.forEach((originalCanvas, index) => {\n if (index < clonedCanvases.length) {\n const clonedCanvas = clonedCanvases[index] as HTMLCanvasElement\n\n redrawCanvas(originalCanvas, clonedCanvas)\n }\n })\n}\n\nexport function deepCloneElement(sourceElement: HTMLElement) {\n const objectUrlStore = createSnapshotObjectUrlStore()\n // Create a deep clone of the source element\n const clone = sourceElement.cloneNode(true) as HTMLElement\n\n // Find all iframes in the original element\n const originalIframes = sourceElement.querySelectorAll(\"iframe\")\n // Find all iframes in the cloned element\n const clonedIframes = clone.querySelectorAll(\"iframe\")\n\n // Handle canvases in the main document\n redrawCanvases(sourceElement, clone)\n\n const copyContents$ = combineLatest([\n from(\n copyBlobAssetReferences(\n clone,\n sourceElement.ownerDocument,\n objectUrlStore,\n ),\n ),\n copyIframeContents(originalIframes, clonedIframes, objectUrlStore),\n ])\n\n return {\n clone,\n ready$: copyContents$.pipe(defaultIfEmpty(true)),\n release: objectUrlStore.revokeAll,\n }\n}\n","import {\n DocumentRenderer,\n type Reader,\n type SpineItem,\n} from \"@prose-reader/core\"\nimport { filter, first, Observable, switchMap } from \"rxjs\"\nimport { deepCloneElement } from \"./utils/deepCloneElement\"\n\nconst SNAPSHOT_CLASS = \"prose-reader-enhancer-gallery-snapshot\"\nconst SNAPSHOT_MASK_CLASS = \"prose-reader-enhancer-gallery-snapshot-mask\"\nconst SNAPSHOT_PREVIEW_CLASS = \"prose-reader-enhancer-gallery-snapshot-preview\"\nconst SNAPSHOT_FRAME_CLASS = \"prose-reader-enhancer-gallery-snapshot-frame\"\n\nconst createSnapshotItem = (doc: Document) => {\n const spineItemContainerElement = doc.createElement(\"div\")\n spineItemContainerElement.classList.add(SNAPSHOT_CLASS)\n spineItemContainerElement.tabIndex = -1\n spineItemContainerElement.setAttribute(\"aria-hidden\", \"true\")\n spineItemContainerElement.setAttribute(\"inert\", \"\")\n\n const contentMask = doc.createElement(\"div\")\n\n contentMask.classList.add(SNAPSHOT_MASK_CLASS)\n\n spineItemContainerElement.appendChild(contentMask)\n\n return spineItemContainerElement\n}\n\nconst makeSnapshotPreviewInert = (element: HTMLElement) => {\n element.classList.add(SNAPSHOT_PREVIEW_CLASS)\n element.tabIndex = -1\n element.setAttribute(\"aria-hidden\", \"true\")\n element.setAttribute(\"inert\", \"\")\n\n element.querySelectorAll(\"iframe\").forEach((iframe) => {\n iframe.classList.add(SNAPSHOT_FRAME_CLASS)\n iframe.tabIndex = -1\n iframe.setAttribute(\"aria-hidden\", \"true\")\n iframe.setAttribute(\"inert\", \"\")\n })\n}\n\nexport class Snapshot extends Observable<HTMLElement> {\n constructor(\n reader: Reader,\n item: SpineItem,\n parent: Element,\n options: {\n height: number\n width: number\n },\n ) {\n super((subscriber) => {\n const parentDocument = parent.ownerDocument\n const unlockSpineItem = reader.spine.spineItemsLoader.forceOpen([item])\n let hasUnlockedSpineItem = false\n let releaseSnapshotAssets = () => {}\n let snapshotItem: HTMLElement | undefined\n\n const unlock = () => {\n if (hasUnlockedSpineItem) return\n\n hasUnlockedSpineItem = true\n unlockSpineItem()\n }\n\n const subscription = item.isReady$\n .pipe(\n filter((isReady) => isReady),\n first(),\n switchMap(() => {\n snapshotItem = createSnapshotItem(parentDocument)\n\n const pageSize = reader.viewport.value.pageSize\n const itemElement = snapshotItem\n const contentMask = itemElement?.children[0] as\n | HTMLElement\n | undefined\n\n if (!itemElement || !contentMask)\n throw new Error(\"No item element or content mask\")\n\n contentMask.style.top = \"0\"\n contentMask.style.left = \"0\"\n\n const measure = options\n const { height, width } = item.layoutInfo\n const numberOfPages = item.numberOfPages\n const widthScaleFullFrame = (measure.width / width) * numberOfPages\n const heightScale = measure.height / height\n\n // Use the minimum scale to ensure the element fits within both dimensions\n const scale = Math.min(widthScaleFullFrame, heightScale)\n\n const {\n clone: clonedElement,\n ready$: cloneReady$,\n release,\n } = deepCloneElement(item.element)\n releaseSnapshotAssets = release\n\n // cleanup unwanted elements from the spine\n Array.from(clonedElement.children).forEach((child) => {\n if (\n !child.classList.contains(\n DocumentRenderer.DOCUMENT_CONTAINER_CLASS_NAME,\n )\n ) {\n child.remove()\n }\n })\n\n clonedElement.style.left = \"0\"\n clonedElement.style.top = \"0\"\n clonedElement.style.position = \"relative\"\n makeSnapshotPreviewInert(clonedElement)\n\n /**\n * Now we adjust the mask to make it fit in the center and cover\n * only the required part of the spine item (hidding) the overflowing\n * pages for example.\n */\n const pageWidthAfterScale = pageSize.width * scale\n const pageHeightAfterScale = pageSize.height * scale\n\n contentMask.style.width = `${pageSize.width}px`\n contentMask.style.height = `${pageSize.height}px`\n contentMask.style.transformOrigin = \"0 0\"\n contentMask.style.transform = `scale(${scale})`\n\n if (pageWidthAfterScale < measure.width) {\n const gap = (measure.width - pageWidthAfterScale) / 2\n\n contentMask.style.left = `${gap}px`\n }\n\n if (pageHeightAfterScale < measure.height) {\n const gap = (measure.height - pageHeightAfterScale) / 2\n\n contentMask.style.top = `${gap}px`\n }\n\n parent.appendChild(itemElement)\n contentMask.appendChild(clonedElement)\n\n subscriber.next(itemElement)\n\n return cloneReady$\n }),\n )\n .subscribe({\n error: (error) => {\n unlock()\n subscriber.error(error)\n },\n complete: () => {\n unlock()\n // Keep the observable open after cloning so the thumbnail owns its\n // copied object URLs until React unsubscribes from this snapshot.\n },\n })\n\n return () => {\n subscription.unsubscribe()\n unlock()\n releaseSnapshotAssets()\n snapshotItem?.remove()\n }\n })\n }\n}\n",".prose-reader-enhancer-gallery-snapshot {\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.prose-reader-enhancer-gallery-snapshot-mask {\n width: 100%;\n height: 100%;\n position: absolute;\n top: 0;\n left: 0;\n overflow: hidden;\n}\n\n.prose-reader-enhancer-gallery-snapshot-preview {\n position: relative;\n top: 0;\n left: 0;\n}\n\n.prose-reader-enhancer-gallery-snapshot,\n.prose-reader-enhancer-gallery-snapshot-mask,\n.prose-reader-enhancer-gallery-snapshot-preview,\n.prose-reader-enhancer-gallery-snapshot-frame,\n.prose-reader-enhancer-gallery-snapshot iframe {\n pointer-events: none;\n user-select: none;\n -webkit-user-select: none;\n}\n","import { injectCSS, type Reader } from \"@prose-reader/core\"\nimport { Snapshot } from \"./Snapshot\"\nimport styles from \"./style.css?inline\"\nimport type { GalleryEnhancerAPI } from \"./types\"\n\nexport type { GalleryEnhancerAPI }\n\nconst STYLE_ID = \"prose-reader-enhancer-gallery-snapshot-styles\"\n\nexport const galleryEnhancer =\n <InheritOptions, InheritOutput extends Reader>(\n next: (options: InheritOptions) => InheritOutput,\n ) =>\n (options: InheritOptions): InheritOutput & GalleryEnhancerAPI => {\n const reader = next(options)\n\n if (typeof document !== \"undefined\" && !document.getElementById(STYLE_ID)) {\n injectCSS(document, STYLE_ID, styles)\n }\n\n return {\n ...reader,\n __PROSE_READER_ENHANCER_GALLERY: true,\n gallery: {\n snapshot: (spineItem, parent, options) =>\n new Snapshot(reader, spineItem, parent, options),\n },\n }\n }\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prose-reader/enhancer-gallery",
3
- "version": "1.303.0",
3
+ "version": "1.305.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.umd.cjs",
6
6
  "module": "./dist/index.js",
@@ -20,7 +20,7 @@
20
20
  "test": "vitest run --coverage"
21
21
  },
22
22
  "dependencies": {
23
- "@prose-reader/core": "^1.303.0"
23
+ "@prose-reader/core": "^1.305.0"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "rxjs": "*"
@@ -28,5 +28,5 @@
28
28
  "devDependencies": {
29
29
  "rxjs": "*"
30
30
  },
31
- "gitHead": "dddc06869ba852fa280e050c1c1929433bb91c5e"
31
+ "gitHead": "9c94c0d55718d2054c2f12702d05464a361c717f"
32
32
  }