vue-book-reader
Version:
vue-book-reader is a vue wrapper for [foliate-js](https://github.com/johnfactotum/foliate-js) - library for rendering e-books in the browser. Supports EPUB, MOBI, KF8 (AZW3), FB2, CBZ, PDF (experimental; requires PDF.js), or add support for other formats
224 lines (223 loc) • 9.47 kB
JavaScript
var K = Object.defineProperty;
var Q = (r, h, t) => h in r ? K(r, h, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[h] = t;
var D = (r, h, t) => (Q(r, typeof h != "symbol" ? h + "" : h, t), t), W = (r, h, t) => {
if (!h.has(r))
throw TypeError("Cannot " + t);
};
var n = (r, h, t) => (W(r, h, "read from private field"), t ? t.call(r) : h.get(r)), f = (r, h, t) => {
if (h.has(r))
throw TypeError("Cannot add the same private member more than once");
h instanceof WeakSet ? h.add(r) : h.set(r, t);
}, p = (r, h, t, e) => (W(r, h, "write to private field"), e ? e.call(r, t) : h.set(r, t), t);
var c = (r, h, t) => (W(r, h, "access private method"), t);
const I = (r) => {
var h, t;
return (t = (h = r == null ? void 0 : r.split(/[,;\s]/)) == null ? void 0 : h.filter((e) => e)) == null ? void 0 : t.map((e) => e.split("=").map((i) => i.trim()));
}, U = (r, h) => {
var i, s;
if (r.documentElement.localName === "svg") {
const [, , a, o] = ((i = r.documentElement.getAttribute("viewBox")) == null ? void 0 : i.split(/\s/)) ?? [];
return { width: a, height: o };
}
const t = I((s = r.querySelector('meta[name="viewport"]')) == null ? void 0 : s.getAttribute("content"));
if (t)
return Object.fromEntries(t);
if (typeof h == "string")
return I(h);
if (h)
return h;
const e = r.querySelector("img");
return e ? { width: e.naturalWidth, height: e.naturalHeight } : (console.warn(new Error("Missing viewport properties")), { width: 1e3, height: 2e3 });
};
var k, j, x, S, L, w, y, b, v, A, H, E, C, M, N, R, P, V, G, T, z;
class X extends HTMLElement {
constructor() {
super();
f(this, A);
f(this, E);
f(this, M);
f(this, R);
f(this, V);
f(this, T);
f(this, k, this.attachShadow({ mode: "closed" }));
f(this, j, new ResizeObserver(() => c(this, E, C).call(this)));
f(this, x, void 0);
f(this, S, -1);
D(this, "defaultViewport");
D(this, "spread");
f(this, L, !1);
f(this, w, void 0);
f(this, y, void 0);
f(this, b, void 0);
f(this, v, void 0);
const t = new CSSStyleSheet();
n(this, k).adoptedStyleSheets = [t], t.replaceSync(`:host {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}`), n(this, j).observe(this);
}
open(t) {
this.book = t;
const { rendition: e } = t;
this.spread = e == null ? void 0 : e.spread, this.defaultViewport = e == null ? void 0 : e.viewport;
const i = t.dir === "rtl", s = !i;
this.rtl = i, (e == null ? void 0 : e.spread) === "none" ? p(this, x, t.sections.map((a) => ({ center: a }))) : p(this, x, t.sections.reduce((a, o) => {
const l = a[a.length - 1], { linear: m, pageSpread: g } = o;
if (m === "no")
return a;
const u = () => {
const d = {};
return a.push(d), d;
};
if (g === "center") {
const d = l.left || l.right ? u() : l;
d.center = o;
} else if (g === "left") {
const d = l.center || l.left || s ? u() : l;
d.left = o;
} else if (g === "right") {
const d = l.center || l.right || i ? u() : l;
d.right = o;
} else
s ? l.center || l.right ? u().left = o : l.left ? l.right = o : l.left = o : l.center || l.left ? u().right = o : l.right ? l.left = o : l.right = o;
return a;
}, [{}]));
}
get index() {
const t = n(this, x)[n(this, S)], e = (t == null ? void 0 : t.center) ?? (this.side === "left" ? t.left ?? t.right : t.right ?? t.left);
return this.book.sections.indexOf(e);
}
getSpreadOf(t) {
const e = n(this, x);
for (let i = 0; i < e.length; i++) {
const { left: s, right: a, center: o } = e[i];
if (s === t)
return { index: i, side: "left" };
if (a === t)
return { index: i, side: "right" };
if (o === t)
return { index: i, side: "center" };
}
}
async goToSpread(t, e, i) {
var a, o, l, m, g, u;
if (t < 0 || t > n(this, x).length - 1)
return;
if (t === n(this, S)) {
c(this, E, C).call(this, e);
return;
}
p(this, S, t);
const s = n(this, x)[t];
if (s.center) {
const d = this.book.sections.indexOf(s.center), O = await ((o = (a = s.center) == null ? void 0 : a.load) == null ? void 0 : o.call(a));
await c(this, M, N).call(this, { center: { index: d, src: O } });
} else {
const d = this.book.sections.indexOf(s.left), O = this.book.sections.indexOf(s.right), $ = await ((m = (l = s.left) == null ? void 0 : l.load) == null ? void 0 : m.call(l)), B = await ((u = (g = s.right) == null ? void 0 : g.load) == null ? void 0 : u.call(g)), F = { index: d, src: $ }, q = { index: O, src: B };
await c(this, M, N).call(this, { left: F, right: q, side: e });
}
c(this, T, z).call(this, i);
}
async select(t) {
await this.goTo(t);
}
async goTo(t) {
const { book: e } = this, i = await t, s = e.sections[i.index];
if (!s)
return;
const { index: a, side: o } = this.getSpreadOf(s);
await this.goToSpread(a, o);
}
async next() {
if (this.rtl ? c(this, R, P).call(this) : c(this, V, G).call(this))
c(this, T, z).call(this, "page");
else
return this.goToSpread(n(this, S) + 1, this.rtl ? "right" : "left", "page");
}
async prev() {
if (this.rtl ? c(this, V, G).call(this) : c(this, R, P).call(this))
c(this, T, z).call(this, "page");
else
return this.goToSpread(n(this, S) - 1, this.rtl ? "left" : "right", "page");
}
getContents() {
return Array.from(n(this, k).querySelectorAll("iframe"), (t) => ({
doc: t.contentDocument
// TODO: index, overlayer
}));
}
destroy() {
n(this, j).unobserve(this);
}
}
k = new WeakMap(), j = new WeakMap(), x = new WeakMap(), S = new WeakMap(), L = new WeakMap(), w = new WeakMap(), y = new WeakMap(), b = new WeakMap(), v = new WeakMap(), A = new WeakSet(), H = async function({ index: t, src: e }) {
const i = document.createElement("div"), s = document.createElement("iframe");
return i.append(s), Object.assign(s.style, {
border: "0",
display: "none",
overflow: "hidden"
}), s.setAttribute("sandbox", "allow-same-origin allow-scripts"), s.setAttribute("scrolling", "no"), s.setAttribute("part", "filter"), n(this, k).append(i), e ? new Promise((a) => {
const o = () => {
s.removeEventListener("load", o);
const l = s.contentDocument;
this.dispatchEvent(new CustomEvent("load", { detail: { doc: l, index: t } }));
const { width: m, height: g } = U(l, this.defaultViewport);
a({
element: i,
iframe: s,
width: parseFloat(m),
height: parseFloat(g)
});
};
s.addEventListener("load", o), s.src = e;
}) : { blank: !0, element: i, iframe: s };
}, E = new WeakSet(), C = function(t = n(this, v)) {
if (!t)
return;
const e = n(this, w) ?? {}, i = n(this, b) ?? n(this, y), s = t === "left" ? e : i, { width: a, height: o } = this.getBoundingClientRect(), l = this.spread !== "both" && this.spread !== "portrait" && o > a;
p(this, L, l);
const m = e.width ?? i.width, g = e.height ?? i.height, u = l || n(this, b) ? Math.min(
a / (s.width ?? m),
o / (s.height ?? g)
) : Math.min(
a / ((e.width ?? m) + (i.width ?? m)),
o / Math.max(
e.height ?? g,
i.height ?? g
)
), d = (O) => {
const { element: $, iframe: B, width: F, height: q, blank: J } = O;
Object.assign(B.style, {
width: `${F}px`,
height: `${q}px`,
transform: `scale(${u})`,
transformOrigin: "top left",
display: J ? "none" : "block"
}), Object.assign($.style, {
width: `${(F ?? m) * u}px`,
height: `${(q ?? g) * u}px`,
overflow: "hidden",
display: "block"
}), l && O !== s && ($.style.display = "none");
};
n(this, b) ? d(n(this, b)) : (d(e), d(i));
}, M = new WeakSet(), N = async function({ left: t, right: e, center: i, side: s }) {
n(this, k).replaceChildren(), p(this, w, null), p(this, y, null), p(this, b, null), i ? (p(this, b, await c(this, A, H).call(this, i)), p(this, v, "center"), c(this, E, C).call(this)) : (p(this, w, await c(this, A, H).call(this, t)), p(this, y, await c(this, A, H).call(this, e)), p(this, v, n(this, w).blank ? "right" : n(this, y).blank ? "left" : s), c(this, E, C).call(this));
}, R = new WeakSet(), P = function() {
var t, e, i, s;
if (!(n(this, b) || (t = n(this, w)) != null && t.blank) && n(this, L) && ((s = (i = (e = n(this, w)) == null ? void 0 : e.element) == null ? void 0 : i.style) == null ? void 0 : s.display) === "none")
return n(this, y).element.style.display = "none", n(this, w).element.style.display = "block", p(this, v, "left"), !0;
}, V = new WeakSet(), G = function() {
var t, e, i, s;
if (!(n(this, b) || (t = n(this, y)) != null && t.blank) && n(this, L) && ((s = (i = (e = n(this, y)) == null ? void 0 : e.element) == null ? void 0 : i.style) == null ? void 0 : s.display) === "none")
return n(this, w).element.style.display = "none", n(this, y).element.style.display = "block", p(this, v, "right"), !0;
}, T = new WeakSet(), z = function(t) {
this.dispatchEvent(new CustomEvent("relocate", { detail: { reason: t, range: null, index: this.index, fraction: 0, size: 1 } }));
};
customElements.define("foliate-fxl", X);
export {
X as FixedLayout
};