@prose-reader/enhancer-gallery 1.297.0 → 1.299.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 +110 -106
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +1 -1
- package/dist/index.umd.cjs.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { waitForFrameLoad as
|
|
2
|
-
import { combineLatest as
|
|
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
3
|
const F = (e, t) => {
|
|
4
4
|
try {
|
|
5
5
|
t.width = e.width, t.height = e.height;
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
} catch (
|
|
6
|
+
const r = t.getContext("2d");
|
|
7
|
+
r && r.drawImage(e, 0, 0);
|
|
8
|
+
} catch (r) {
|
|
9
9
|
console.warn(
|
|
10
10
|
"Could not copy canvas content - possible tainted canvas or cross-origin issue",
|
|
11
|
-
|
|
11
|
+
r
|
|
12
12
|
);
|
|
13
13
|
}
|
|
14
|
-
},
|
|
14
|
+
}, W = [
|
|
15
15
|
"img",
|
|
16
16
|
"video",
|
|
17
17
|
"audio",
|
|
18
18
|
"source",
|
|
19
19
|
"link",
|
|
20
20
|
"script"
|
|
21
|
-
].join(","),
|
|
21
|
+
].join(","), B = () => {
|
|
22
22
|
const e = /* @__PURE__ */ new Set();
|
|
23
23
|
return {
|
|
24
24
|
add: (t) => {
|
|
@@ -30,157 +30,161 @@ const F = (e, t) => {
|
|
|
30
30
|
}), e.clear();
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
|
-
},
|
|
33
|
+
}, z = (e) => e.getAttribute("src") || e.getAttribute("href"), V = (e, t) => {
|
|
34
34
|
e.hasAttribute("src") ? e.setAttribute("src", t) : e.hasAttribute("href") && e.setAttribute("href", t);
|
|
35
|
-
},
|
|
36
|
-
const
|
|
35
|
+
}, Y = async (e, t, r) => {
|
|
36
|
+
const o = await (await fetch(e)).blob(), n = t.defaultView?.URL.createObjectURL(o);
|
|
37
37
|
if (n)
|
|
38
|
-
return
|
|
39
|
-
},
|
|
40
|
-
const
|
|
41
|
-
e.querySelectorAll(
|
|
38
|
+
return r.add(n), n;
|
|
39
|
+
}, L = async (e, t, r) => {
|
|
40
|
+
const s = Array.from(
|
|
41
|
+
e.querySelectorAll(W)
|
|
42
42
|
);
|
|
43
43
|
await Promise.all(
|
|
44
|
-
|
|
45
|
-
const n =
|
|
44
|
+
s.map(async (o) => {
|
|
45
|
+
const n = z(o);
|
|
46
46
|
if (!n?.startsWith("blob:")) return;
|
|
47
|
-
let
|
|
47
|
+
let a;
|
|
48
48
|
try {
|
|
49
|
-
|
|
50
|
-
} catch (
|
|
51
|
-
console.error("Error copying snapshot blob asset:",
|
|
49
|
+
a = await Y(n, t, r);
|
|
50
|
+
} catch (i) {
|
|
51
|
+
console.error("Error copying snapshot blob asset:", i);
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
|
-
|
|
54
|
+
a && V(o, a);
|
|
55
55
|
})
|
|
56
56
|
);
|
|
57
|
-
},
|
|
58
|
-
const
|
|
59
|
-
(
|
|
60
|
-
const
|
|
61
|
-
return
|
|
62
|
-
|
|
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
63
|
try {
|
|
64
|
-
if (
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
const
|
|
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
68
|
Array.from(
|
|
69
|
-
|
|
69
|
+
f.querySelectorAll('style, link[rel="stylesheet"]')
|
|
70
70
|
).forEach((u) => {
|
|
71
|
-
|
|
72
|
-
}), await
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
71
|
+
y.appendChild(u.cloneNode(!0));
|
|
72
|
+
}), await L(
|
|
73
|
+
a.contentDocument,
|
|
74
|
+
a.contentDocument,
|
|
75
|
+
r
|
|
76
76
|
);
|
|
77
77
|
}
|
|
78
78
|
return !0;
|
|
79
|
-
} catch (
|
|
80
|
-
return console.error("Error copying iframe content:",
|
|
79
|
+
} catch (i) {
|
|
80
|
+
return console.error("Error copying iframe content:", i), !1;
|
|
81
81
|
}
|
|
82
82
|
})
|
|
83
|
-
) :
|
|
83
|
+
) : S(!0);
|
|
84
84
|
}
|
|
85
85
|
);
|
|
86
|
-
return
|
|
87
|
-
},
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
if (n <
|
|
91
|
-
const
|
|
92
|
-
F(
|
|
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
93
|
}
|
|
94
94
|
});
|
|
95
95
|
};
|
|
96
|
-
function
|
|
97
|
-
const t =
|
|
98
|
-
|
|
99
|
-
const n =
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
103
|
e.ownerDocument,
|
|
104
104
|
t
|
|
105
105
|
)
|
|
106
106
|
),
|
|
107
|
-
|
|
107
|
+
G(s, o, t)
|
|
108
108
|
]);
|
|
109
109
|
return {
|
|
110
|
-
clone:
|
|
111
|
-
ready$: n.pipe(
|
|
110
|
+
clone: r,
|
|
111
|
+
ready$: n.pipe(H(!0)),
|
|
112
112
|
release: t.revokeAll
|
|
113
113
|
};
|
|
114
114
|
}
|
|
115
|
-
const
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
return
|
|
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
|
+
});
|
|
120
124
|
};
|
|
121
|
-
class
|
|
122
|
-
constructor(t,
|
|
125
|
+
class ne extends M {
|
|
126
|
+
constructor(t, r, s, o) {
|
|
123
127
|
super((n) => {
|
|
124
|
-
const s = t.spine.spineItemsLoader.forceOpen([
|
|
125
|
-
let
|
|
126
|
-
},
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
},
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
if (!m || !
|
|
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)
|
|
136
140
|
throw new Error("No item element or content mask");
|
|
137
|
-
|
|
138
|
-
const h =
|
|
139
|
-
clone:
|
|
140
|
-
ready$:
|
|
141
|
-
release:
|
|
142
|
-
} =
|
|
143
|
-
y =
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
) ||
|
|
147
|
-
}),
|
|
148
|
-
const
|
|
149
|
-
if (
|
|
150
|
-
const
|
|
151
|
-
|
|
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`;
|
|
152
156
|
}
|
|
153
|
-
if (
|
|
154
|
-
const
|
|
155
|
-
|
|
157
|
+
if (w < h.height) {
|
|
158
|
+
const p = (h.height - w) / 2;
|
|
159
|
+
c.style.top = `${p}px`;
|
|
156
160
|
}
|
|
157
|
-
return
|
|
161
|
+
return s.appendChild(m), c.appendChild(d), n.next(m), U;
|
|
158
162
|
})
|
|
159
163
|
).subscribe({
|
|
160
|
-
error: (
|
|
161
|
-
|
|
164
|
+
error: (l) => {
|
|
165
|
+
g(), n.error(l);
|
|
162
166
|
},
|
|
163
167
|
complete: () => {
|
|
164
|
-
|
|
168
|
+
g();
|
|
165
169
|
}
|
|
166
170
|
});
|
|
167
171
|
return () => {
|
|
168
|
-
|
|
172
|
+
I.unsubscribe(), g(), y(), u?.remove();
|
|
169
173
|
};
|
|
170
174
|
});
|
|
171
175
|
}
|
|
172
176
|
}
|
|
173
|
-
const
|
|
174
|
-
const
|
|
175
|
-
return {
|
|
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,
|
|
177
181
|
__PROSE_READER_ENHANCER_GALLERY: !0,
|
|
178
182
|
gallery: {
|
|
179
|
-
snapshot: (
|
|
183
|
+
snapshot: (s, o, n) => new ne(r, s, o, n)
|
|
180
184
|
}
|
|
181
185
|
};
|
|
182
186
|
};
|
|
183
187
|
export {
|
|
184
|
-
|
|
188
|
+
ce as galleryEnhancer
|
|
185
189
|
};
|
|
186
190
|
//# 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 createSnapshotItem = () => {\n const spineItemContainerElement = document.createElement(\"div\")\n spineItemContainerElement.style.width = `100%`\n spineItemContainerElement.style.height = `100%`\n spineItemContainerElement.style.position = \"relative\"\n spineItemContainerElement.style.overflow = \"hidden\"\n\n const contentMask = document.createElement(\"div\")\n\n contentMask.style.width = \"100%\"\n contentMask.style.height = \"100%\"\n contentMask.style.position = \"absolute\"\n contentMask.style.top = \"0\"\n contentMask.style.left = \"0\"\n contentMask.style.overflow = \"hidden\"\n\n spineItemContainerElement.appendChild(contentMask)\n\n return spineItemContainerElement\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 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()\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 // mask reset\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\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 type { Reader } from \"@prose-reader/core\"\nimport { Snapshot } from \"./Snapshot\"\nimport type { GalleryEnhancerAPI } from \"./types\"\n\nexport type { GalleryEnhancerAPI }\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 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","createSnapshotItem","spineItemContainerElement","contentMask","Snapshot","Observable","reader","item","parent","options","subscriber","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","galleryEnhancer","next","spineItem"],"mappings":"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"}
|
|
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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"}
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(function(i,
|
|
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
2
|
//# sourceMappingURL=index.umd.cjs.map
|
package/dist/index.umd.cjs.map
CHANGED
|
@@ -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 createSnapshotItem = () => {\n const spineItemContainerElement = document.createElement(\"div\")\n spineItemContainerElement.style.width = `100%`\n spineItemContainerElement.style.height = `100%`\n spineItemContainerElement.style.position = \"relative\"\n spineItemContainerElement.style.overflow = \"hidden\"\n\n const contentMask = document.createElement(\"div\")\n\n contentMask.style.width = \"100%\"\n contentMask.style.height = \"100%\"\n contentMask.style.position = \"absolute\"\n contentMask.style.top = \"0\"\n contentMask.style.left = \"0\"\n contentMask.style.overflow = \"hidden\"\n\n spineItemContainerElement.appendChild(contentMask)\n\n return spineItemContainerElement\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 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()\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 // mask reset\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\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 type { Reader } from \"@prose-reader/core\"\nimport { Snapshot } from \"./Snapshot\"\nimport type { GalleryEnhancerAPI } from \"./types\"\n\nexport type { GalleryEnhancerAPI }\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 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","createSnapshotItem","spineItemContainerElement","contentMask","Snapshot","Observable","reader","item","parent","options","subscriber","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","galleryEnhancer","next","spineItem"],"mappings":"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"}
|
|
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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prose-reader/enhancer-gallery",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.299.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.
|
|
23
|
+
"@prose-reader/core": "^1.299.0"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"rxjs": "*"
|
|
@@ -28,5 +28,5 @@
|
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"rxjs": "*"
|
|
30
30
|
},
|
|
31
|
-
"gitHead": "
|
|
31
|
+
"gitHead": "30ebdd7f5e3398cfa38b3e9c1c8db8d70e15aa3e"
|
|
32
32
|
}
|