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
243 lines (242 loc) • 7.73 kB
JavaScript
var R = (n, t, e) => {
if (!t.has(n))
throw TypeError("Cannot " + e);
};
var s = (n, t, e) => (R(n, t, "read from private field"), e ? e.call(n) : t.get(n)), f = (n, t, e) => {
if (t.has(n))
throw TypeError("Cannot add the same private member more than once");
t instanceof WeakSet ? t.add(n) : t.set(n, e);
}, c = (n, t, e, i) => (R(n, t, "write to private field"), i ? i.call(n, e) : t.set(n, e), e);
var b = (n, t, e) => (R(n, t, "access private method"), e);
const l = {
XML: "http://www.w3.org/XML/1998/namespace",
SSML: "http://www.w3.org/2001/10/synthesis"
}, D = /* @__PURE__ */ new Set([
"article",
"aside",
"audio",
"blockquote",
"caption",
"details",
"dialog",
"div",
"dl",
"dt",
"dd",
"figure",
"footer",
"form",
"figcaption",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"header",
"hgroup",
"hr",
"li",
"main",
"math",
"nav",
"ol",
"p",
"pre",
"section",
"tr"
]), _ = (n) => {
var e;
const t = n.lang || ((e = n == null ? void 0 : n.getAttributeNS) == null ? void 0 : e.call(n, l.XML, "lang"));
return t || (n.parentElement ? _(n.parentElement) : null);
}, O = (n) => {
var e;
const t = (e = n == null ? void 0 : n.getAttributeNS) == null ? void 0 : e.call(n, l.XML, "lang");
return t || (n.parentElement ? O(n.parentElement) : null);
}, q = (n = "en", t = "word") => {
const e = new Intl.Segmenter(n, { granularity: t }), i = t === "word";
return function* (r, a) {
const g = r.join("");
let N = 0, o = -1, u = 0;
for (const { index: x, segment: E, isWordLike: p } of e.segment(g)) {
if (i && !p)
continue;
for (; u <= x; )
u += r[++o].length;
const L = o, W = x - (u - r[o].length), v = x + E.length;
if (v < g.length)
for (; u <= v; )
u += r[++o].length;
const z = o, B = v - (u - r[o].length);
yield [
(N++).toString(),
a(L, W, z, B)
];
}
};
}, F = (n, t) => {
const e = document.implementation.createDocument(l.SSML, "speak"), { lang: i } = t;
i && e.documentElement.setAttributeNS(l.XML, "lang", i);
const r = (a, g, N) => {
if (!a)
return;
if (a.nodeType === 3)
return e.createTextNode(a.textContent);
if (a.nodeType === 4)
return e.createCDATASection(a.textContent);
if (a.nodeType !== 1)
return;
let o;
const u = a.nodeName.toLowerCase();
u === "foliate-mark" ? (o = e.createElementNS(l.SSML, "mark"), o.setAttribute("name", a.dataset.name)) : u === "br" ? o = e.createElementNS(l.SSML, "break") : (u === "em" || u === "strong") && (o = e.createElementNS(l.SSML, "emphasis"));
const x = a.lang || a.getAttributeNS(l.XML, "lang");
x && (o || (o = e.createElementNS(l.SSML, "lang")), o.setAttributeNS(l.XML, "lang", x));
const E = a.getAttributeNS(l.SSML, "alphabet") || N;
if (!o) {
const L = a.getAttributeNS(l.SSML, "ph");
L && (o = e.createElementNS(l.SSML, "phoneme"), E && o.setAttribute("alphabet", E), o.setAttribute("ph", L));
}
o || (o = g);
let p = a.firstChild;
for (; p; ) {
const L = r(p, o, E);
L && o !== L && o.append(L), p = p.nextSibling;
}
return o;
};
return r(n.firstChild, e.documentElement, t.alphabet), e;
}, P = (n, t, e) => {
const i = _(n.commonAncestorContainer), r = O(n.commonAncestorContainer), a = q(i, e), g = n.cloneContents(), N = [...t(n, a)], o = [...t(g, a)];
for (const [x, E] of o) {
const p = document.createElement("foliate-mark");
p.dataset.name = x, E.insertNode(p);
}
const u = F(g, { lang: i, alphabet: r });
return { entries: N, ssml: u };
}, X = (n) => !n.toString().trim();
function* j(n) {
let t;
const e = n.createTreeWalker(n.body, NodeFilter.SHOW_ELEMENT);
for (let i = e.nextNode(); i; i = e.nextNode()) {
const r = i.tagName.toLowerCase();
D.has(r) && (t && (t.setEndBefore(i), X(t) || (yield t)), t = n.createRange(), t.setStart(i, 0));
}
t || (t = n.createRange(), t.setStart(n.body.firstChild ?? n.body, 0)), t.setEndAfter(n.body.lastChild ?? n.body), X(t) || (yield t);
}
var h, k, m, d;
class H {
constructor(t, e = (i) => i) {
f(this, h, []);
f(this, k, void 0);
f(this, m, -1);
f(this, d, void 0);
c(this, k, t), c(this, d, e);
}
current() {
if (s(this, h)[s(this, m)])
return s(this, d).call(this, s(this, h)[s(this, m)]);
}
first() {
if (s(this, h)[0])
return c(this, m, 0), s(this, d).call(this, s(this, h)[0]);
}
prev() {
const t = s(this, m) - 1;
if (s(this, h)[t])
return c(this, m, t), s(this, d).call(this, s(this, h)[t]);
}
next() {
const t = s(this, m) + 1;
if (s(this, h)[t])
return c(this, m, t), s(this, d).call(this, s(this, h)[t]);
for (; ; ) {
const { done: e, value: i } = s(this, k).next();
if (e)
break;
if (s(this, h).push(i), s(this, h)[t])
return c(this, m, t), s(this, d).call(this, s(this, h)[t]);
}
}
find(t) {
const e = s(this, h).findIndex((i) => t(i));
if (e > -1)
return c(this, m, e), s(this, d).call(this, s(this, h)[e]);
for (; ; ) {
const { done: i, value: r } = s(this, k).next();
if (i)
break;
if (s(this, h).push(r), t(r))
return c(this, m, s(this, h).length - 1), s(this, d).call(this, r);
}
}
}
h = new WeakMap(), k = new WeakMap(), m = new WeakMap(), d = new WeakMap();
var w, A, S, C, y, I, M, T;
class G {
constructor(t, e, i) {
f(this, y);
f(this, M);
f(this, w, void 0);
f(this, A, void 0);
f(this, S, void 0);
f(this, C, new XMLSerializer());
this.doc = t, this.highlight = i, c(this, w, new H(j(t), (r) => {
const { entries: a, ssml: g } = P(r, e);
return c(this, A, new Map(a)), [g, r];
}));
}
start() {
c(this, S, null);
const [t] = s(this, w).first() ?? [];
return t ? b(this, M, T).call(this, t, (e) => b(this, y, I).call(this, e, s(this, S))) : this.next();
}
resume() {
const [t] = s(this, w).current() ?? [];
return t ? b(this, M, T).call(this, t, (e) => b(this, y, I).call(this, e, s(this, S))) : this.next();
}
prev(t) {
c(this, S, null);
const [e, i] = s(this, w).prev() ?? [];
return t && i && this.highlight(i.cloneRange()), b(this, M, T).call(this, e);
}
next(t) {
c(this, S, null);
const [e, i] = s(this, w).next() ?? [];
return t && i && this.highlight(i.cloneRange()), b(this, M, T).call(this, e);
}
from(t) {
c(this, S, null);
const [e] = s(this, w).find((r) => t.compareBoundaryPoints(Range.END_TO_START, r) <= 0);
let i;
for (const [r, a] of s(this, A).entries())
if (t.compareBoundaryPoints(Range.START_TO_START, a) <= 0) {
i = r;
break;
}
return b(this, M, T).call(this, e, (r) => b(this, y, I).call(this, r, i));
}
setMark(t) {
const e = s(this, A).get(t);
e && (c(this, S, t), this.highlight(e.cloneRange()));
}
}
w = new WeakMap(), A = new WeakMap(), S = new WeakMap(), C = new WeakMap(), y = new WeakSet(), I = function(t, e) {
return e ? t.querySelector(`mark[name="${CSS.escape(e)}"`) : null;
}, M = new WeakSet(), T = function(t, e) {
var a, g;
if (!t)
return;
if (!e)
return s(this, C).serializeToString(t);
const i = document.implementation.createDocument(l.SSML, "speak");
i.documentElement.replaceWith(i.importNode(t.documentElement, !0));
let r = (a = e(i)) == null ? void 0 : a.previousSibling;
for (; r; ) {
const N = r.previousSibling ?? ((g = r.parentNode) == null ? void 0 : g.previousSibling);
r.parentNode.removeChild(r), r = N;
}
return s(this, C).serializeToString(i);
};
export {
G as TTS
};