@prose-reader/enhancer-gallery 1.203.0 → 1.204.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/Snapshot.d.ts +1 -1
- package/dist/index.js +89 -110
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +1 -1
- package/dist/index.umd.cjs.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/utils/copyIframeContents.d.ts +1 -0
- package/dist/utils/deepCloneElement.d.ts +4 -1
- package/dist/utils/redrawCanvas.d.ts +1 -0
- package/package.json +3 -3
package/dist/Snapshot.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Reader, SpineItem } from '@prose-reader/core';
|
|
2
2
|
import { Observable } from 'rxjs';
|
|
3
3
|
export declare class Snapshot extends Observable<HTMLElement> {
|
|
4
|
-
constructor(reader: Reader, item: SpineItem, options: {
|
|
4
|
+
constructor(reader: Reader, item: SpineItem, parent: Element, options: {
|
|
5
5
|
height: number;
|
|
6
6
|
width: number;
|
|
7
7
|
});
|
package/dist/index.js
CHANGED
|
@@ -1,134 +1,113 @@
|
|
|
1
|
-
import { DocumentRenderer as
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import { waitForFrameLoad as N, DocumentRenderer as $ } from "@prose-reader/core";
|
|
2
|
+
import { defaultIfEmpty as b, combineLatest as D, of as u, switchMap as w, Observable as R, filter as x, first as O, tap as _, finalize as L } from "rxjs";
|
|
3
|
+
const M = (t, e) => {
|
|
4
|
+
try {
|
|
5
|
+
e.width = t.width, e.height = t.height;
|
|
6
|
+
const n = e.getContext("2d");
|
|
7
|
+
n && n.drawImage(t, 0, 0);
|
|
8
|
+
} catch (n) {
|
|
9
|
+
console.warn(
|
|
10
|
+
"Could not copy canvas content - possible tainted canvas or cross-origin issue",
|
|
11
|
+
n
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
}, k = (t, e) => D(
|
|
15
|
+
Array.from(t).map((n, s) => {
|
|
16
|
+
const o = e[s];
|
|
17
|
+
return o ? N(u(o)).pipe(
|
|
18
|
+
w(() => {
|
|
19
|
+
try {
|
|
20
|
+
if (n.contentDocument && o.contentDocument) {
|
|
21
|
+
const r = n.contentDocument.body.cloneNode(!0);
|
|
22
|
+
o.contentDocument.body.replaceWith(r);
|
|
23
|
+
const d = n.contentDocument.head, l = o.contentDocument.head;
|
|
24
|
+
Array.from(
|
|
25
|
+
d.querySelectorAll('style, link[rel="stylesheet"]')
|
|
26
|
+
).forEach((a) => {
|
|
27
|
+
l.appendChild(a.cloneNode(!0));
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return u(!0);
|
|
31
|
+
} catch (r) {
|
|
32
|
+
return console.error("Error copying iframe content:", r), u(!1);
|
|
16
33
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
}, d = () => {
|
|
28
|
-
o(), e.removeEventListener("load", d);
|
|
29
|
-
};
|
|
30
|
-
e.addEventListener("load", d), ((y = t.contentDocument) == null ? void 0 : y.readyState) === "complete" && o();
|
|
31
|
-
});
|
|
32
|
-
const p = l.querySelectorAll("canvas"), v = s.querySelectorAll("canvas");
|
|
33
|
-
return p.forEach((t, r) => {
|
|
34
|
-
if (r < v.length) {
|
|
35
|
-
const e = v[r];
|
|
36
|
-
try {
|
|
37
|
-
e.width = t.width, e.height = t.height;
|
|
38
|
-
const o = e.getContext("2d");
|
|
39
|
-
o && o.drawImage(t, 0, 0);
|
|
40
|
-
} catch (o) {
|
|
41
|
-
console.warn(
|
|
42
|
-
"Could not copy canvas content - possible tainted canvas or cross-origin issue",
|
|
43
|
-
o
|
|
44
|
-
);
|
|
45
|
-
}
|
|
34
|
+
})
|
|
35
|
+
) : u(!0);
|
|
36
|
+
})
|
|
37
|
+
), q = (t, e) => {
|
|
38
|
+
const n = t.querySelectorAll("canvas"), s = e.querySelectorAll("canvas");
|
|
39
|
+
n.forEach((o, r) => {
|
|
40
|
+
if (r < s.length) {
|
|
41
|
+
const d = s[r];
|
|
42
|
+
M(o, d);
|
|
46
43
|
}
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (a < u.length) {
|
|
58
|
-
const i = u[a];
|
|
59
|
-
try {
|
|
60
|
-
i.width = m.width, i.height = m.height;
|
|
61
|
-
const f = i.getContext("2d");
|
|
62
|
-
f && f.drawImage(m, 0, 0);
|
|
63
|
-
} catch (f) {
|
|
64
|
-
console.warn("Could not copy iframe canvas content", f);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
} catch (h) {
|
|
69
|
-
console.error("Error copying iframe canvases:", h);
|
|
70
|
-
}
|
|
71
|
-
}, d = () => {
|
|
72
|
-
o(), e.removeEventListener("load", d);
|
|
73
|
-
};
|
|
74
|
-
e.addEventListener("load", d), ((y = t.contentDocument) == null ? void 0 : y.readyState) === "complete" && o();
|
|
75
|
-
}), s;
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
function F(t) {
|
|
47
|
+
const e = t.cloneNode(!0), n = t.querySelectorAll("iframe"), s = e.querySelectorAll("iframe");
|
|
48
|
+
q(t, e);
|
|
49
|
+
const o = k(n, s);
|
|
50
|
+
return {
|
|
51
|
+
clone: e,
|
|
52
|
+
ready$: o.pipe(b(!0))
|
|
53
|
+
};
|
|
76
54
|
}
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
const c = document.createElement("div");
|
|
83
|
-
return c.style.width = "100%", c.style.height = "100%", c.style.position = "absolute", c.style.top = "0", c.style.left = "0", c.style.overflow = "hidden", n.appendChild(c), n;
|
|
55
|
+
const H = () => {
|
|
56
|
+
const t = document.createElement("div");
|
|
57
|
+
t.style.width = "100%", t.style.height = "100%", t.style.position = "relative", t.style.overflow = "hidden";
|
|
58
|
+
const e = document.createElement("div");
|
|
59
|
+
return e.style.width = "100%", e.style.height = "100%", e.style.position = "absolute", e.style.top = "0", e.style.left = "0", e.style.overflow = "hidden", t.appendChild(e), t;
|
|
84
60
|
};
|
|
85
|
-
class
|
|
86
|
-
constructor(
|
|
87
|
-
super((
|
|
88
|
-
const
|
|
61
|
+
class z extends R {
|
|
62
|
+
constructor(e, n, s, o) {
|
|
63
|
+
super((r) => {
|
|
64
|
+
const d = e.spine.spineItemsLoader.forceOpen([n]);
|
|
89
65
|
return n.isReady$.pipe(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
if (!
|
|
66
|
+
x((l) => l),
|
|
67
|
+
O(),
|
|
68
|
+
w(() => {
|
|
69
|
+
const l = H(), a = e.viewport.value.pageSize, y = l, c = y == null ? void 0 : y.children[0];
|
|
70
|
+
if (!y || !c)
|
|
95
71
|
throw new Error("No item element or content mask");
|
|
96
|
-
|
|
97
|
-
const
|
|
98
|
-
Array.from(
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
) ||
|
|
102
|
-
}),
|
|
103
|
-
const
|
|
104
|
-
if (
|
|
105
|
-
const
|
|
106
|
-
|
|
72
|
+
c.style.top = "0", c.style.left = "0";
|
|
73
|
+
const i = o, { height: E, width: A } = n.layout.layoutInfo, S = n.numberOfPages, v = i.width / A * S, C = i.height / E, f = Math.min(v, C), { clone: p, ready$: I } = F(n.element);
|
|
74
|
+
Array.from(p.children).forEach((h) => {
|
|
75
|
+
h.classList.contains(
|
|
76
|
+
$.DOCUMENT_CONTAINER_CLASS_NAME
|
|
77
|
+
) || h.remove();
|
|
78
|
+
}), p.style.left = "0", p.style.top = "0", p.style.position = "relative";
|
|
79
|
+
const m = a.width * f, g = a.height * f;
|
|
80
|
+
if (c.style.width = `${a.width}px`, c.style.height = `${a.height}px`, c.style.transformOrigin = "0 0", c.style.transform = `scale(${f})`, m < i.width) {
|
|
81
|
+
const h = (i.width - m) / 2;
|
|
82
|
+
c.style.left = `${h}px`;
|
|
107
83
|
}
|
|
108
|
-
if (
|
|
109
|
-
const
|
|
110
|
-
|
|
84
|
+
if (g < i.height) {
|
|
85
|
+
const h = (i.height - g) / 2;
|
|
86
|
+
c.style.top = `${h}px`;
|
|
111
87
|
}
|
|
112
|
-
return
|
|
88
|
+
return s.appendChild(l), c.appendChild(p), r.next(l), I;
|
|
89
|
+
}),
|
|
90
|
+
_(() => {
|
|
91
|
+
r.complete();
|
|
113
92
|
}),
|
|
114
|
-
|
|
115
|
-
|
|
93
|
+
L(() => {
|
|
94
|
+
d();
|
|
116
95
|
})
|
|
117
96
|
).subscribe();
|
|
118
97
|
});
|
|
119
98
|
}
|
|
120
99
|
}
|
|
121
|
-
const
|
|
122
|
-
const n =
|
|
100
|
+
const W = (t) => (e) => {
|
|
101
|
+
const n = t(e);
|
|
123
102
|
return {
|
|
124
103
|
...n,
|
|
125
104
|
__PROSE_READER_ENHANCER_GALLERY: !0,
|
|
126
105
|
gallery: {
|
|
127
|
-
snapshot: (
|
|
106
|
+
snapshot: (s, o, r) => new z(n, s, o, r)
|
|
128
107
|
}
|
|
129
108
|
};
|
|
130
109
|
};
|
|
131
110
|
export {
|
|
132
|
-
|
|
111
|
+
W as galleryEnhancer
|
|
133
112
|
};
|
|
134
113
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/utils/deepCloneElement.ts","../src/Snapshot.ts","../src/index.ts"],"sourcesContent":["export function deepCloneElement(sourceElement: HTMLElement) {\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 // Process each iframe\n originalIframes.forEach((originalIframe, index) => {\n const clonedIframe = clonedIframes[index]\n\n if (!clonedIframe) return\n\n const copyStyles = () => {\n try {\n // Check for cross-origin restrictions\n if (!originalIframe.contentDocument || !clonedIframe.contentDocument) {\n console.warn(\n \"Cannot access iframe content document - possible cross-origin restriction\",\n )\n return\n }\n\n // Copy all stylesheets from original iframe to cloned iframe\n const originalStylesheets =\n originalIframe.contentDocument.querySelectorAll(\n 'link[rel=\"stylesheet\"], style',\n )\n\n originalStylesheets.forEach((stylesheet) => {\n const stylesheetClone = stylesheet.cloneNode(true)\n clonedIframe.contentDocument?.head.appendChild(stylesheetClone)\n })\n } catch (e) {\n console.error(\"Error copying iframe styles:\", e)\n }\n }\n\n // Store reference to the handler so we can remove it later\n const loadHandler = () => {\n copyStyles()\n // Remove the event listener after it's been called to prevent memory leaks\n clonedIframe.removeEventListener(\"load\", loadHandler)\n }\n\n // Add load event listener to the cloned iframe\n clonedIframe.addEventListener(\"load\", loadHandler)\n\n // If the original iframe is already loaded, trigger the handler\n if (originalIframe.contentDocument?.readyState === \"complete\") {\n copyStyles()\n }\n })\n\n // Handle canvases in the main document\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 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 })\n\n // Also handle canvases inside iframes\n originalIframes.forEach((originalIframe, index) => {\n const clonedIframe = clonedIframes[index]\n\n if (!clonedIframe) return\n\n const copyCanvases = () => {\n try {\n if (!originalIframe.contentDocument || !clonedIframe.contentDocument) {\n return\n }\n\n const originalCanvasesInIframe =\n originalIframe.contentDocument.querySelectorAll(\"canvas\")\n const clonedCanvasesInIframe =\n clonedIframe.contentDocument.querySelectorAll(\"canvas\")\n\n originalCanvasesInIframe.forEach((originalCanvas, canvasIndex) => {\n if (canvasIndex < clonedCanvasesInIframe.length) {\n const clonedCanvas = clonedCanvasesInIframe[\n canvasIndex\n ] as 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 (canvasError) {\n console.warn(\"Could not copy iframe canvas content\", canvasError)\n }\n }\n })\n } catch (e) {\n console.error(\"Error copying iframe canvases:\", e)\n }\n }\n\n // Store reference to the handler so we can remove it later\n const canvasLoadHandler = () => {\n copyCanvases()\n // Remove the event listener after it's been called to prevent memory leaks\n clonedIframe.removeEventListener(\"load\", canvasLoadHandler)\n }\n\n // Add load event listener to copy canvases after iframe loads\n clonedIframe.addEventListener(\"load\", canvasLoadHandler)\n\n // If the original iframe is already loaded, trigger the handler\n if (originalIframe.contentDocument?.readyState === \"complete\") {\n copyCanvases()\n }\n })\n\n return clone\n}\n","import {\n DocumentRenderer,\n type Reader,\n type SpineItem,\n} from \"@prose-reader/core\"\nimport { Observable, filter, first, of, switchMap, tap } from \"rxjs\"\nimport { deepCloneElement } from \"./utils/deepCloneElement\"\n\nconst createGridItem = (options: {\n height: number\n width: number\n}) => {\n const gridItemElement = document.createElement(\"div\")\n gridItemElement.style.width = `${options.width}px`\n gridItemElement.style.height = `${options.height}px`\n gridItemElement.style.position = \"relative\"\n\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 // gridItemElement.appendChild(spineItemContainerElement)\n\n return spineItemContainerElement\n}\n\nexport class Snapshot extends Observable<HTMLElement> {\n constructor(\n reader: Reader,\n item: SpineItem,\n options: {\n height: number\n width: number\n },\n ) {\n super((subscriber) => {\n const gridItem = createGridItem(options)\n\n return item.isReady$\n .pipe(\n filter((isReady) => isReady),\n first(),\n switchMap(() => {\n const pageSize = reader.viewport.value.pageSize\n const itemElement = gridItem\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 // itemElement.style.aspectRatio = `${pageSize.width / pageSize.height}`\n\n const measure = options\n const { height, width } = item.layout.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 clonedElement = deepCloneElement(item.element)\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 // clonedElement.style.transformOrigin = \"0 0\"\n // clonedElement.style.transform = `scale(${scale})`\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 = `${pageWidthAfterScale}px`\n contentMask.style.width = `${pageSize.width}px`\n // contentMask.style.height = `${pageHeightAfterScale}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 contentMask.innerHTML = \"\"\n contentMask.appendChild(clonedElement)\n\n return of(gridItem)\n }),\n tap((gridItem) => {\n subscriber.next(gridItem)\n subscriber.complete()\n }),\n )\n .subscribe()\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, options) =>\n new Snapshot(reader, spineItem, options),\n },\n }\n }\n"],"names":["deepCloneElement","sourceElement","clone","originalIframes","clonedIframes","originalIframe","index","clonedIframe","copyStyles","stylesheet","stylesheetClone","_a","e","loadHandler","originalCanvases","clonedCanvases","originalCanvas","clonedCanvas","context","copyCanvases","originalCanvasesInIframe","clonedCanvasesInIframe","canvasIndex","canvasError","canvasLoadHandler","createGridItem","options","gridItemElement","spineItemContainerElement","contentMask","Snapshot","Observable","reader","item","subscriber","gridItem","filter","isReady","first","switchMap","pageSize","itemElement","measure","height","width","numberOfPages","widthScaleFullFrame","heightScale","scale","clonedElement","child","DocumentRenderer","pageWidthAfterScale","pageHeightAfterScale","gap","of","tap","galleryEnhancer","next","spineItem"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/utils/redrawCanvas.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","import { waitForFrameLoad } from \"@prose-reader/core\"\nimport { combineLatest, defaultIfEmpty, of, switchMap } from \"rxjs\"\nimport { redrawCanvas } from \"./redrawCanvas\"\n\nconst copyIframeContents = (\n originalIframes: NodeListOf<HTMLIFrameElement>,\n clonedIframes: NodeListOf<HTMLIFrameElement>,\n) => {\n return combineLatest(\n Array.from(originalIframes).map((originalIframe, index) => {\n const clonedIframe = clonedIframes[index]\n\n if (!clonedIframe) return of(true)\n\n return waitForFrameLoad(of(clonedIframe)).pipe(\n switchMap(() => {\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 return of(true)\n } catch (e) {\n console.error(\"Error copying iframe content:\", e)\n return of(false)\n }\n }),\n )\n }),\n )\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 // 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$ = copyIframeContents(originalIframes, clonedIframes)\n\n return {\n clone,\n ready$: copyContents$.pipe(defaultIfEmpty(true)),\n }\n}\n","import {\n DocumentRenderer,\n type Reader,\n type SpineItem,\n} from \"@prose-reader/core\"\nimport { Observable, filter, finalize, first, switchMap, tap } 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 unlock = reader.spine.spineItemsLoader.forceOpen([item])\n\n return item.isReady$\n .pipe(\n filter((isReady) => isReady),\n first(),\n switchMap(() => {\n const 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.layout.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 { clone: clonedElement, ready$: cloneReady$ } =\n deepCloneElement(item.element)\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(snapshotItem)\n contentMask.appendChild(clonedElement)\n\n subscriber.next(snapshotItem)\n\n return cloneReady$\n }),\n tap(() => {\n subscriber.complete()\n }),\n finalize(() => {\n unlock()\n }),\n )\n .subscribe()\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","copyIframeContents","originalIframes","clonedIframes","combineLatest","originalIframe","index","clonedIframe","waitForFrameLoad","of","switchMap","clonedBody","originalHead","clonedHead","node","redrawCanvases","sourceElement","clone","originalCanvases","clonedCanvases","deepCloneElement","copyContents$","defaultIfEmpty","createSnapshotItem","spineItemContainerElement","contentMask","Snapshot","Observable","reader","item","parent","options","subscriber","unlock","filter","isReady","first","snapshotItem","pageSize","itemElement","measure","height","width","numberOfPages","widthScaleFullFrame","heightScale","scale","clonedElement","cloneReady$","child","DocumentRenderer","pageWidthAfterScale","pageHeightAfterScale","gap","tap","finalize","galleryEnhancer","next","spineItem"],"mappings":"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"}
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(function(d
|
|
1
|
+
(function(a,d){typeof exports=="object"&&typeof module<"u"?d(exports,require("@prose-reader/core"),require("rxjs")):typeof define=="function"&&define.amd?define(["exports","@prose-reader/core","rxjs"],d):(a=typeof globalThis<"u"?globalThis:a||self,d(a["prose-reader-enhancer-gallery"]={},a.core,a.rxjs))})(this,function(a,d,o){"use strict";const S=(t,e)=>{try{e.width=t.width,e.height=t.height;const n=e.getContext("2d");n&&n.drawImage(t,0,0)}catch(n){console.warn("Could not copy canvas content - possible tainted canvas or cross-origin issue",n)}},v=(t,e)=>o.combineLatest(Array.from(t).map((n,s)=>{const r=e[s];return r?d.waitForFrameLoad(o.of(r)).pipe(o.switchMap(()=>{try{if(n.contentDocument&&r.contentDocument){const c=n.contentDocument.body.cloneNode(!0);r.contentDocument.body.replaceWith(c);const u=n.contentDocument.head,i=r.contentDocument.head;Array.from(u.querySelectorAll('style, link[rel="stylesheet"]')).forEach(h=>{i.appendChild(h.cloneNode(!0))})}return o.of(!0)}catch(c){return console.error("Error copying iframe content:",c),o.of(!1)}})):o.of(!0)})),A=(t,e)=>{const n=t.querySelectorAll("canvas"),s=e.querySelectorAll("canvas");n.forEach((r,c)=>{if(c<s.length){const u=s[c];S(r,u)}})};function C(t){const e=t.cloneNode(!0),n=t.querySelectorAll("iframe"),s=e.querySelectorAll("iframe");A(t,e);const r=v(n,s);return{clone:e,ready$:r.pipe(o.defaultIfEmpty(!0))}}const b=()=>{const t=document.createElement("div");t.style.width="100%",t.style.height="100%",t.style.position="relative",t.style.overflow="hidden";const e=document.createElement("div");return e.style.width="100%",e.style.height="100%",e.style.position="absolute",e.style.top="0",e.style.left="0",e.style.overflow="hidden",t.appendChild(e),t};class I extends o.Observable{constructor(e,n,s,r){super(c=>{const u=e.spine.spineItemsLoader.forceOpen([n]);return n.isReady$.pipe(o.filter(i=>i),o.first(),o.switchMap(()=>{const i=b(),h=e.viewport.value.pageSize,m=i,l=m==null?void 0:m.children[0];if(!m||!l)throw new Error("No item element or content mask");l.style.top="0",l.style.left="0";const p=r,{height:$,width:D}=n.layout.layoutInfo,O=n.numberOfPages,R=p.width/D*O,M=p.height/$,g=Math.min(R,M),{clone:y,ready$:_}=C(n.element);Array.from(y.children).forEach(f=>{f.classList.contains(d.DocumentRenderer.DOCUMENT_CONTAINER_CLASS_NAME)||f.remove()}),y.style.left="0",y.style.top="0",y.style.position="relative";const w=h.width*g,E=h.height*g;if(l.style.width=`${h.width}px`,l.style.height=`${h.height}px`,l.style.transformOrigin="0 0",l.style.transform=`scale(${g})`,w<p.width){const f=(p.width-w)/2;l.style.left=`${f}px`}if(E<p.height){const f=(p.height-E)/2;l.style.top=`${f}px`}return s.appendChild(i),l.appendChild(y),c.next(i),_}),o.tap(()=>{c.complete()}),o.finalize(()=>{u()})).subscribe()})}}const N=t=>e=>{const n=t(e);return{...n,__PROSE_READER_ENHANCER_GALLERY:!0,gallery:{snapshot:(s,r,c)=>new I(n,s,r,c)}}};a.galleryEnhancer=N,Object.defineProperty(a,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/deepCloneElement.ts","../src/Snapshot.ts","../src/index.ts"],"sourcesContent":["export function deepCloneElement(sourceElement: HTMLElement) {\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 // Process each iframe\n originalIframes.forEach((originalIframe, index) => {\n const clonedIframe = clonedIframes[index]\n\n if (!clonedIframe) return\n\n const copyStyles = () => {\n try {\n // Check for cross-origin restrictions\n if (!originalIframe.contentDocument || !clonedIframe.contentDocument) {\n console.warn(\n \"Cannot access iframe content document - possible cross-origin restriction\",\n )\n return\n }\n\n // Copy all stylesheets from original iframe to cloned iframe\n const originalStylesheets =\n originalIframe.contentDocument.querySelectorAll(\n 'link[rel=\"stylesheet\"], style',\n )\n\n originalStylesheets.forEach((stylesheet) => {\n const stylesheetClone = stylesheet.cloneNode(true)\n clonedIframe.contentDocument?.head.appendChild(stylesheetClone)\n })\n } catch (e) {\n console.error(\"Error copying iframe styles:\", e)\n }\n }\n\n // Store reference to the handler so we can remove it later\n const loadHandler = () => {\n copyStyles()\n // Remove the event listener after it's been called to prevent memory leaks\n clonedIframe.removeEventListener(\"load\", loadHandler)\n }\n\n // Add load event listener to the cloned iframe\n clonedIframe.addEventListener(\"load\", loadHandler)\n\n // If the original iframe is already loaded, trigger the handler\n if (originalIframe.contentDocument?.readyState === \"complete\") {\n copyStyles()\n }\n })\n\n // Handle canvases in the main document\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 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 })\n\n // Also handle canvases inside iframes\n originalIframes.forEach((originalIframe, index) => {\n const clonedIframe = clonedIframes[index]\n\n if (!clonedIframe) return\n\n const copyCanvases = () => {\n try {\n if (!originalIframe.contentDocument || !clonedIframe.contentDocument) {\n return\n }\n\n const originalCanvasesInIframe =\n originalIframe.contentDocument.querySelectorAll(\"canvas\")\n const clonedCanvasesInIframe =\n clonedIframe.contentDocument.querySelectorAll(\"canvas\")\n\n originalCanvasesInIframe.forEach((originalCanvas, canvasIndex) => {\n if (canvasIndex < clonedCanvasesInIframe.length) {\n const clonedCanvas = clonedCanvasesInIframe[\n canvasIndex\n ] as 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 (canvasError) {\n console.warn(\"Could not copy iframe canvas content\", canvasError)\n }\n }\n })\n } catch (e) {\n console.error(\"Error copying iframe canvases:\", e)\n }\n }\n\n // Store reference to the handler so we can remove it later\n const canvasLoadHandler = () => {\n copyCanvases()\n // Remove the event listener after it's been called to prevent memory leaks\n clonedIframe.removeEventListener(\"load\", canvasLoadHandler)\n }\n\n // Add load event listener to copy canvases after iframe loads\n clonedIframe.addEventListener(\"load\", canvasLoadHandler)\n\n // If the original iframe is already loaded, trigger the handler\n if (originalIframe.contentDocument?.readyState === \"complete\") {\n copyCanvases()\n }\n })\n\n return clone\n}\n","import {\n DocumentRenderer,\n type Reader,\n type SpineItem,\n} from \"@prose-reader/core\"\nimport { Observable, filter, first, of, switchMap, tap } from \"rxjs\"\nimport { deepCloneElement } from \"./utils/deepCloneElement\"\n\nconst createGridItem = (options: {\n height: number\n width: number\n}) => {\n const gridItemElement = document.createElement(\"div\")\n gridItemElement.style.width = `${options.width}px`\n gridItemElement.style.height = `${options.height}px`\n gridItemElement.style.position = \"relative\"\n\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 // gridItemElement.appendChild(spineItemContainerElement)\n\n return spineItemContainerElement\n}\n\nexport class Snapshot extends Observable<HTMLElement> {\n constructor(\n reader: Reader,\n item: SpineItem,\n options: {\n height: number\n width: number\n },\n ) {\n super((subscriber) => {\n const gridItem = createGridItem(options)\n\n return item.isReady$\n .pipe(\n filter((isReady) => isReady),\n first(),\n switchMap(() => {\n const pageSize = reader.viewport.value.pageSize\n const itemElement = gridItem\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 // itemElement.style.aspectRatio = `${pageSize.width / pageSize.height}`\n\n const measure = options\n const { height, width } = item.layout.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 clonedElement = deepCloneElement(item.element)\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 // clonedElement.style.transformOrigin = \"0 0\"\n // clonedElement.style.transform = `scale(${scale})`\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 = `${pageWidthAfterScale}px`\n contentMask.style.width = `${pageSize.width}px`\n // contentMask.style.height = `${pageHeightAfterScale}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 contentMask.innerHTML = \"\"\n contentMask.appendChild(clonedElement)\n\n return of(gridItem)\n }),\n tap((gridItem) => {\n subscriber.next(gridItem)\n subscriber.complete()\n }),\n )\n .subscribe()\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, options) =>\n new Snapshot(reader, spineItem, options),\n },\n }\n }\n"],"names":["deepCloneElement","sourceElement","clone","originalIframes","clonedIframes","originalIframe","index","clonedIframe","copyStyles","stylesheet","stylesheetClone","_a","e","loadHandler","originalCanvases","clonedCanvases","originalCanvas","clonedCanvas","context","copyCanvases","originalCanvasesInIframe","clonedCanvasesInIframe","canvasIndex","canvasError","canvasLoadHandler","createGridItem","options","gridItemElement","spineItemContainerElement","contentMask","Snapshot","Observable","reader","item","subscriber","gridItem","filter","isReady","first","switchMap","pageSize","itemElement","measure","height","width","numberOfPages","widthScaleFullFrame","heightScale","scale","clonedElement","child","DocumentRenderer","pageWidthAfterScale","pageHeightAfterScale","gap","of","tap","galleryEnhancer","next","spineItem"],"mappings":"oVAAO,SAASA,EAAiBC,EAA4B,CAErD,MAAAC,EAAQD,EAAc,UAAU,EAAI,EAGpCE,EAAkBF,EAAc,iBAAiB,QAAQ,EAEzDG,EAAgBF,EAAM,iBAAiB,QAAQ,EAGrCC,EAAA,QAAQ,CAACE,EAAgBC,IAAU,OAC3C,MAAAC,EAAeH,EAAcE,CAAK,EAExC,GAAI,CAACC,EAAc,OAEnB,MAAMC,EAAa,IAAM,CACnB,GAAA,CAEF,GAAI,CAACH,EAAe,iBAAmB,CAACE,EAAa,gBAAiB,CAC5D,QAAA,KACN,2EACF,EACA,MAAA,CAKAF,EAAe,gBAAgB,iBAC7B,+BACF,EAEkB,QAASI,GAAe,OACpC,MAAAC,EAAkBD,EAAW,UAAU,EAAI,GACpCE,EAAAJ,EAAA,kBAAA,MAAAI,EAAiB,KAAK,YAAYD,EAAe,CAC/D,QACME,EAAG,CACF,QAAA,MAAM,+BAAgCA,CAAC,CAAA,CAEnD,EAGMC,EAAc,IAAM,CACbL,EAAA,EAEED,EAAA,oBAAoB,OAAQM,CAAW,CACtD,EAGaN,EAAA,iBAAiB,OAAQM,CAAW,IAG7CF,EAAAN,EAAe,kBAAf,YAAAM,EAAgC,cAAe,YACtCH,EAAA,CACb,CACD,EAGK,MAAAM,EAAmBb,EAAc,iBAAiB,QAAQ,EAC1Dc,EAAiBb,EAAM,iBAAiB,QAAQ,EAErC,OAAAY,EAAA,QAAQ,CAACE,EAAgBV,IAAU,CAC9C,GAAAA,EAAQS,EAAe,OAAQ,CAC3B,MAAAE,EAAeF,EAAeT,CAAK,EAErC,GAAA,CAEFW,EAAa,MAAQD,EAAe,MACpCC,EAAa,OAASD,EAAe,OAG/B,MAAAE,EAAUD,EAAa,WAAW,IAAI,EACxCC,GACMA,EAAA,UAAUF,EAAgB,EAAG,CAAC,QAEjCJ,EAAG,CACF,QAAA,KACN,gFACAA,CACF,CAAA,CACF,CACF,CACD,EAGeT,EAAA,QAAQ,CAACE,EAAgBC,IAAU,OAC3C,MAAAC,EAAeH,EAAcE,CAAK,EAExC,GAAI,CAACC,EAAc,OAEnB,MAAMY,EAAe,IAAM,CACrB,GAAA,CACF,GAAI,CAACd,EAAe,iBAAmB,CAACE,EAAa,gBACnD,OAGF,MAAMa,EACJf,EAAe,gBAAgB,iBAAiB,QAAQ,EACpDgB,EACJd,EAAa,gBAAgB,iBAAiB,QAAQ,EAE/Ba,EAAA,QAAQ,CAACJ,EAAgBM,IAAgB,CAC5D,GAAAA,EAAcD,EAAuB,OAAQ,CACzC,MAAAJ,EAAeI,EACnBC,CACF,EAEI,GAAA,CAEFL,EAAa,MAAQD,EAAe,MACpCC,EAAa,OAASD,EAAe,OAG/B,MAAAE,EAAUD,EAAa,WAAW,IAAI,EACxCC,GACMA,EAAA,UAAUF,EAAgB,EAAG,CAAC,QAEjCO,EAAa,CACZ,QAAA,KAAK,uCAAwCA,CAAW,CAAA,CAClE,CACF,CACD,QACMX,EAAG,CACF,QAAA,MAAM,iCAAkCA,CAAC,CAAA,CAErD,EAGMY,EAAoB,IAAM,CACjBL,EAAA,EAEAZ,EAAA,oBAAoB,OAAQiB,CAAiB,CAC5D,EAGajB,EAAA,iBAAiB,OAAQiB,CAAiB,IAGnDb,EAAAN,EAAe,kBAAf,YAAAM,EAAgC,cAAe,YACpCQ,EAAA,CACf,CACD,EAEMjB,CACT,CCvIA,MAAMuB,EAAkBC,GAGlB,CACE,MAAAC,EAAkB,SAAS,cAAc,KAAK,EACpDA,EAAgB,MAAM,MAAQ,GAAGD,EAAQ,KAAK,KAC9CC,EAAgB,MAAM,OAAS,GAAGD,EAAQ,MAAM,KAChDC,EAAgB,MAAM,SAAW,WAE3B,MAAAC,EAA4B,SAAS,cAAc,KAAK,EAC9DA,EAA0B,MAAM,MAAQ,OACxCA,EAA0B,MAAM,OAAS,OACzCA,EAA0B,MAAM,SAAW,WAC3CA,EAA0B,MAAM,SAAW,SAErC,MAAAC,EAAc,SAAS,cAAc,KAAK,EAEhD,OAAAA,EAAY,MAAM,MAAQ,OAC1BA,EAAY,MAAM,OAAS,OAC3BA,EAAY,MAAM,SAAW,WAC7BA,EAAY,MAAM,IAAM,IACxBA,EAAY,MAAM,KAAO,IACzBA,EAAY,MAAM,SAAW,SAE7BD,EAA0B,YAAYC,CAAW,EAG1CD,CACT,EAEO,MAAME,UAAiBC,EAAAA,UAAwB,CACpD,YACEC,EACAC,EACAP,EAIA,CACA,MAAOQ,GAAe,CACd,MAAAC,EAAWV,EAAeC,CAAO,EAEvC,OAAOO,EAAK,SACT,KACCG,SAAQC,GAAYA,CAAO,EAC3BC,QAAM,EACNC,EAAAA,UAAU,IAAM,CACR,MAAAC,EAAWR,EAAO,SAAS,MAAM,SACjCS,EAAcN,EACdN,EAAcY,GAAA,YAAAA,EAAa,SAAS,GAItC,GAAA,CAACA,GAAe,CAACZ,EACb,MAAA,IAAI,MAAM,iCAAiC,EAGnDA,EAAY,MAAM,IAAM,IACxBA,EAAY,MAAM,KAAO,IAIzB,MAAMa,EAAUhB,EACV,CAAE,OAAAiB,EAAQ,MAAAC,CAAM,EAAIX,EAAK,OAAO,WAChCY,EAAgBZ,EAAK,cACrBa,EAAuBJ,EAAQ,MAAQE,EAASC,EAChDE,EAAcL,EAAQ,OAASC,EAG/BK,EAAQ,KAAK,IAAIF,EAAqBC,CAAW,EAEjDE,EAAgBjD,EAAiBiC,EAAK,OAAO,EAGnD,MAAM,KAAKgB,EAAc,QAAQ,EAAE,QAASC,GAAU,CAEjDA,EAAM,UAAU,SACfC,mBAAiB,6BAAA,GAGnBD,EAAM,OAAO,CACf,CACD,EAEDD,EAAc,MAAM,KAAO,IAC3BA,EAAc,MAAM,IAAM,IAC1BA,EAAc,MAAM,SAAW,WASzB,MAAAG,EAAsBZ,EAAS,MAAQQ,EACvCK,EAAuBb,EAAS,OAASQ,EAS3C,GANJnB,EAAY,MAAM,MAAQ,GAAGW,EAAS,KAAK,KAE3CX,EAAY,MAAM,OAAS,GAAGW,EAAS,MAAM,KAC7CX,EAAY,MAAM,gBAAkB,MACxBA,EAAA,MAAM,UAAY,SAASmB,CAAK,IAExCI,EAAsBV,EAAQ,MAAO,CACjC,MAAAY,GAAOZ,EAAQ,MAAQU,GAAuB,EAExCvB,EAAA,MAAM,KAAO,GAAGyB,CAAG,IAAA,CAG7B,GAAAD,EAAuBX,EAAQ,OAAQ,CACnC,MAAAY,GAAOZ,EAAQ,OAASW,GAAwB,EAE1CxB,EAAA,MAAM,IAAM,GAAGyB,CAAG,IAAA,CAGhC,OAAAzB,EAAY,UAAY,GACxBA,EAAY,YAAYoB,CAAa,EAE9BM,EAAAA,GAAGpB,CAAQ,CAAA,CACnB,EACDqB,EAAA,IAAKrB,GAAa,CAChBD,EAAW,KAAKC,CAAQ,EACxBD,EAAW,SAAS,CACrB,CAAA,GAEF,UAAU,CAAA,CACd,CAAA,CAEL,CCpIO,MAAMuB,EAETC,GAEDhC,GAAgE,CACzD,MAAAM,EAAS0B,EAAKhC,CAAO,EAEpB,MAAA,CACL,GAAGM,EACH,gCAAiC,GACjC,QAAS,CACP,SAAU,CAAC2B,EAAWjC,IACpB,IAAII,EAASE,EAAQ2B,EAAWjC,CAAO,CAAA,CAE7C,CACF"}
|
|
1
|
+
{"version":3,"file":"index.umd.cjs","sources":["../src/utils/redrawCanvas.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","import { waitForFrameLoad } from \"@prose-reader/core\"\nimport { combineLatest, defaultIfEmpty, of, switchMap } from \"rxjs\"\nimport { redrawCanvas } from \"./redrawCanvas\"\n\nconst copyIframeContents = (\n originalIframes: NodeListOf<HTMLIFrameElement>,\n clonedIframes: NodeListOf<HTMLIFrameElement>,\n) => {\n return combineLatest(\n Array.from(originalIframes).map((originalIframe, index) => {\n const clonedIframe = clonedIframes[index]\n\n if (!clonedIframe) return of(true)\n\n return waitForFrameLoad(of(clonedIframe)).pipe(\n switchMap(() => {\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 return of(true)\n } catch (e) {\n console.error(\"Error copying iframe content:\", e)\n return of(false)\n }\n }),\n )\n }),\n )\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 // 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$ = copyIframeContents(originalIframes, clonedIframes)\n\n return {\n clone,\n ready$: copyContents$.pipe(defaultIfEmpty(true)),\n }\n}\n","import {\n DocumentRenderer,\n type Reader,\n type SpineItem,\n} from \"@prose-reader/core\"\nimport { Observable, filter, finalize, first, switchMap, tap } 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 unlock = reader.spine.spineItemsLoader.forceOpen([item])\n\n return item.isReady$\n .pipe(\n filter((isReady) => isReady),\n first(),\n switchMap(() => {\n const 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.layout.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 { clone: clonedElement, ready$: cloneReady$ } =\n deepCloneElement(item.element)\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(snapshotItem)\n contentMask.appendChild(clonedElement)\n\n subscriber.next(snapshotItem)\n\n return cloneReady$\n }),\n tap(() => {\n subscriber.complete()\n }),\n finalize(() => {\n unlock()\n }),\n )\n .subscribe()\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","copyIframeContents","originalIframes","clonedIframes","combineLatest","originalIframe","index","clonedIframe","waitForFrameLoad","of","switchMap","clonedBody","originalHead","clonedHead","node","redrawCanvases","sourceElement","clone","originalCanvases","clonedCanvases","deepCloneElement","copyContents$","defaultIfEmpty","createSnapshotItem","spineItemContainerElement","contentMask","Snapshot","Observable","reader","item","parent","options","subscriber","unlock","filter","isReady","first","snapshotItem","pageSize","itemElement","measure","height","width","numberOfPages","widthScaleFullFrame","heightScale","scale","clonedElement","cloneReady$","child","DocumentRenderer","pageWidthAfterScale","pageHeightAfterScale","gap","tap","finalize","galleryEnhancer","next","spineItem"],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { Observable } from 'rxjs';
|
|
|
3
3
|
export type GalleryEnhancerAPI = {
|
|
4
4
|
readonly __PROSE_READER_ENHANCER_GALLERY: boolean;
|
|
5
5
|
gallery: {
|
|
6
|
-
snapshot: (spineItem: SpineItem, options: {
|
|
6
|
+
snapshot: (spineItem: SpineItem, parent: Element, options: {
|
|
7
7
|
height: number;
|
|
8
8
|
width: number;
|
|
9
9
|
}) => Observable<HTMLElement>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const copyIframeContents: (originalIframes: NodeListOf<HTMLIFrameElement>, clonedIframes: NodeListOf<HTMLIFrameElement>) => import('rxjs').Observable<boolean[]>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const redrawCanvas: (originalCanvas: HTMLCanvasElement, clonedCanvas: HTMLCanvasElement) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prose-reader/enhancer-gallery",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.204.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.204.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": "bef6283c17e2ea04e89e5d990ca59ca5220fafa4"
|
|
32
32
|
}
|