fable-editor 1.2.7 → 1.3.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/angular/core/editor.d.ts +51 -1
- package/dist/angular/core/word-image-paste.d.ts +27 -0
- package/dist/angular/esm2022/core/editor.mjs +266 -20
- package/dist/angular/esm2022/core/word-image-paste.mjs +189 -0
- package/dist/angular/fesm2022/fable-editor.mjs +453 -19
- package/dist/angular/fesm2022/fable-editor.mjs.map +1 -1
- package/dist/core/editor.css +28 -1
- package/dist/core/editor.d.ts +51 -1
- package/dist/core/editor.d.ts.map +1 -1
- package/dist/core/index.cjs +4 -4
- package/dist/core/index.mjs +1008 -765
- package/dist/core/word-image-paste.d.ts +28 -0
- package/dist/core/word-image-paste.d.ts.map +1 -0
- package/dist/react/index.cjs +11 -11
- package/dist/react/index.mjs +1146 -903
- package/package.json +1 -1
- package/style.css +28 -1
package/dist/core/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const rt = {
|
|
2
2
|
en: {
|
|
3
3
|
dir: "ltr",
|
|
4
4
|
file: "File",
|
|
@@ -384,10 +384,10 @@ const it = {
|
|
|
384
384
|
emcat_flags: "أعلام"
|
|
385
385
|
}
|
|
386
386
|
};
|
|
387
|
-
function
|
|
388
|
-
return
|
|
387
|
+
function D(d) {
|
|
388
|
+
return rt[d];
|
|
389
389
|
}
|
|
390
|
-
const
|
|
390
|
+
const at = "undo redo | preview print | importword revhistory | fontfamily fontsize | fontsizeincrease fontsizedecrease | bold italic underline strikethrough | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist | outdent indent | link blockquote code changecase lineheight wordspacing letterspacing | removeformat | blocks | ltr rtl | quickimage quickvideo quicktable codesample template charmap emoji | fullscreen sourcecode", ct = "file edit view insert format tools table help", ht = [
|
|
391
391
|
["Andale Mono", "andale mono,times"],
|
|
392
392
|
["Arial", "arial,helvetica,sans-serif"],
|
|
393
393
|
["Arial Black", "arial black,avant garde"],
|
|
@@ -407,7 +407,7 @@ const st = "undo redo | preview print | importword revhistory | fontfamily fonts
|
|
|
407
407
|
["Verdana", "verdana,geneva"],
|
|
408
408
|
["Webdings", "webdings"],
|
|
409
409
|
["Wingdings", "wingdings,zapf dingbats"]
|
|
410
|
-
],
|
|
410
|
+
], dt = ["8px", "9px", "10px", "11px", "12px", "14px", "16px", "18px", "20px", "24px", "28px", "32px", "36px", "48px", "72px", "96px"], pt = 1, mt = 100, U = ["1", "1.15", "1.4", "1.5", "1.75", "2", "2.5", "3"], W = ["1px", "2px", "4px", "6px", "8px", "12px"], j = ["0.5px", "1px", "1.5px", "2px", "3px", "4px"], V = [
|
|
411
411
|
["plain", "Plain text"],
|
|
412
412
|
["html", "HTML/XML"],
|
|
413
413
|
["css", "CSS"],
|
|
@@ -424,7 +424,7 @@ const st = "undo redo | preview print | importword revhistory | fontfamily fonts
|
|
|
424
424
|
["rust", "Rust"],
|
|
425
425
|
["sql", "SQL"],
|
|
426
426
|
["bash", "Bash/Shell"]
|
|
427
|
-
],
|
|
427
|
+
], X = [
|
|
428
428
|
["p", "para"],
|
|
429
429
|
["h1", "heading1"],
|
|
430
430
|
["h2", "heading2"],
|
|
@@ -433,7 +433,7 @@ const st = "undo redo | preview print | importword revhistory | fontfamily fonts
|
|
|
433
433
|
["h5", "heading5"],
|
|
434
434
|
["h6", "heading6"],
|
|
435
435
|
["pre", "pre"]
|
|
436
|
-
],
|
|
436
|
+
], ut = ["#F76707", "#4263EB", "#CC5DE8"], gt = [
|
|
437
437
|
"#FFFFFF",
|
|
438
438
|
"#F4F4F4",
|
|
439
439
|
"#E8EAED",
|
|
@@ -459,7 +459,7 @@ const st = "undo redo | preview print | importword revhistory | fontfamily fonts
|
|
|
459
459
|
"#8E24AA",
|
|
460
460
|
"#C2185B",
|
|
461
461
|
"#6D4C41"
|
|
462
|
-
],
|
|
462
|
+
], ft = [
|
|
463
463
|
{
|
|
464
464
|
key: "chcat_currency",
|
|
465
465
|
chars: [
|
|
@@ -799,7 +799,7 @@ const st = "undo redo | preview print | importword revhistory | fontfamily fonts
|
|
|
799
799
|
"ة"
|
|
800
800
|
]
|
|
801
801
|
}
|
|
802
|
-
],
|
|
802
|
+
], vt = [
|
|
803
803
|
{
|
|
804
804
|
key: "emcat_smileys",
|
|
805
805
|
chars: [
|
|
@@ -1524,7 +1524,7 @@ const st = "undo redo | preview print | importword revhistory | fontfamily fonts
|
|
|
1524
1524
|
"🇲🇦"
|
|
1525
1525
|
]
|
|
1526
1526
|
}
|
|
1527
|
-
],
|
|
1527
|
+
], Jt = [
|
|
1528
1528
|
"©",
|
|
1529
1529
|
"®",
|
|
1530
1530
|
"™",
|
|
@@ -1573,11 +1573,11 @@ const st = "undo redo | preview print | importword revhistory | fontfamily fonts
|
|
|
1573
1573
|
"ـ",
|
|
1574
1574
|
"٠",
|
|
1575
1575
|
"١"
|
|
1576
|
-
], y = (
|
|
1577
|
-
'<path d="M10 6h10M10 12h10M10 18h10"/>' +
|
|
1576
|
+
], y = (d, t) => `<svg viewBox="${t || "0 0 24 24"}">${d}</svg>`, f = (d) => y(`<path class="f" d="${d}"/>`, "0 -960 960 960"), q = (d, t = 7.5) => y(
|
|
1577
|
+
'<path d="M10 6h10M10 12h10M10 18h10"/>' + d.map(
|
|
1578
1578
|
(e, i) => `<text x="2.5" y="${8.4 + i * 6}" font-size="${t}" stroke="none" fill="#222f3e" font-family="Arial">${e}</text>`
|
|
1579
1579
|
).join("")
|
|
1580
|
-
),
|
|
1580
|
+
), c = {
|
|
1581
1581
|
bold: f(
|
|
1582
1582
|
"M272-200v-560h221q65 0 120 40t55 111q0 51-23 78.5T602-491q25 11 55.5 41t30.5 90q0 89-65 124.5T501-200H272Zm121-112h104q48 0 58.5-24.5T566-372q0-11-10.5-35.5T494-432H393v120Zm0-228h93q33 0 48-17t15-38q0-24-17-39t-44-15h-95v109Z"
|
|
1583
1583
|
),
|
|
@@ -1810,7 +1810,7 @@ const st = "undo redo | preview print | importword revhistory | fontfamily fonts
|
|
|
1810
1810
|
codesampleic: y(
|
|
1811
1811
|
'<rect x="3.5" y="4" width="17" height="16" rx="2"/><path d="M3.5 8.5h17"/><path d="M9.5 12 7 14.25l2.5 2.25M14.5 12l2.5 2.25-2.5 2.25"/>'
|
|
1812
1812
|
)
|
|
1813
|
-
},
|
|
1813
|
+
}, te = (d) => `<span class="txt">${d}</span>`, bt = /* @__PURE__ */ new Set([
|
|
1814
1814
|
"p",
|
|
1815
1815
|
"div",
|
|
1816
1816
|
"span",
|
|
@@ -1852,7 +1852,7 @@ const st = "undo redo | preview print | importword revhistory | fontfamily fonts
|
|
|
1852
1852
|
"figure",
|
|
1853
1853
|
"figcaption",
|
|
1854
1854
|
"mark"
|
|
1855
|
-
]),
|
|
1855
|
+
]), yt = /* @__PURE__ */ new Set([
|
|
1856
1856
|
"text-align",
|
|
1857
1857
|
"direction",
|
|
1858
1858
|
"unicode-bidi",
|
|
@@ -1908,7 +1908,7 @@ const st = "undo redo | preview print | importword revhistory | fontfamily fonts
|
|
|
1908
1908
|
"box-sizing",
|
|
1909
1909
|
"list-style-type",
|
|
1910
1910
|
"white-space"
|
|
1911
|
-
]),
|
|
1911
|
+
]), Q = {
|
|
1912
1912
|
"*": ["dir", "lang", "colspan", "rowspan"],
|
|
1913
1913
|
a: ["href", "target", "rel", "title"],
|
|
1914
1914
|
img: ["src", "alt", "width", "height", "title"],
|
|
@@ -1917,26 +1917,26 @@ const st = "undo redo | preview print | importword revhistory | fontfamily fonts
|
|
|
1917
1917
|
th: ["width", "valign"],
|
|
1918
1918
|
table: ["width", "cellpadding", "cellspacing"]
|
|
1919
1919
|
};
|
|
1920
|
-
function
|
|
1921
|
-
const t = {}, e =
|
|
1920
|
+
function R(d) {
|
|
1921
|
+
const t = {}, e = d.getAttribute && d.getAttribute("style");
|
|
1922
1922
|
return e && e.split(";").forEach((i) => {
|
|
1923
1923
|
const s = i.indexOf(":");
|
|
1924
1924
|
s < 1 || (t[i.slice(0, s).trim().toLowerCase()] = i.slice(s + 1).trim());
|
|
1925
1925
|
}), t;
|
|
1926
1926
|
}
|
|
1927
|
-
function
|
|
1928
|
-
return
|
|
1927
|
+
function xt(d) {
|
|
1928
|
+
return d.replace(/<!--\[if !supportLists\]-->([\s\S]*?)<!--\[endif\]-->/gi, "$1").replace(/<!--\[if !supportLists\]>([\s\S]*?)<!\[endif\]-->/gi, "$1").replace(/<!\[if !supportLists\]>([\s\S]*?)<!\[endif\]>/gi, "$1").replace(/<!--\[if [\s\S]*?<!\[endif\]-->/gi, "").replace(/<!--[\s\S]*?-->/g, "").replace(/<(script|style|xml|title)[\s\S]*?<\/\1>/gi, "").replace(/<\/?(meta|link)[^>]*>/gi, "").replace(/<\?xml[\s\S]*?\?>/gi, "").replace(/<\/?(o|v|w|m|st1):[^>]*>/gi, "");
|
|
1929
1929
|
}
|
|
1930
|
-
function
|
|
1931
|
-
return /^[0-9]+[\.\)،]/.test(
|
|
1930
|
+
function Ct(d) {
|
|
1931
|
+
return /^[0-9]+[\.\)،]/.test(d) ? { ordered: !0 } : /^[٠-٩۰-۹]+/.test(d) ? { ordered: !0, style: "arabic-indic" } : /^[ivxlc]{2,}[\.\)]/.test(d) ? { ordered: !0, style: "lower-roman" } : /^[IVXLC]{2,}[\.\)]/.test(d) ? { ordered: !0, style: "upper-roman" } : /^[a-z][\.\)]/.test(d) ? { ordered: !0, style: "lower-alpha" } : /^[A-Z][\.\)]/.test(d) ? { ordered: !0, style: "upper-alpha" } : /^[ء-ي][\.\)،-]/.test(d) ? { ordered: !0, style: "arabic-indic" } : { ordered: !1 };
|
|
1932
1932
|
}
|
|
1933
|
-
function
|
|
1933
|
+
function wt(d) {
|
|
1934
1934
|
const t = (s) => {
|
|
1935
1935
|
const l = (s.getAttribute("style") || "") + " " + (s.className || "");
|
|
1936
1936
|
return /mso-list\s*:(?!\s*ignore)/i.test(l) || /MsoListParagraph/i.test(l);
|
|
1937
1937
|
}, e = [];
|
|
1938
1938
|
let i = null;
|
|
1939
|
-
Array.from(
|
|
1939
|
+
Array.from(d.body.querySelectorAll("p")).forEach((s) => {
|
|
1940
1940
|
if (!t(s)) {
|
|
1941
1941
|
i = null;
|
|
1942
1942
|
return;
|
|
@@ -1944,67 +1944,67 @@ function vt(p) {
|
|
|
1944
1944
|
const l = s.previousElementSibling;
|
|
1945
1945
|
i && l && i[i.length - 1] === l ? i.push(s) : (i = [s], e.push(i));
|
|
1946
1946
|
}), e.forEach((s) => {
|
|
1947
|
-
const l = [],
|
|
1948
|
-
s.forEach((
|
|
1949
|
-
var x, C,
|
|
1950
|
-
const
|
|
1947
|
+
const l = [], n = s[0];
|
|
1948
|
+
s.forEach((o) => {
|
|
1949
|
+
var x, C, S;
|
|
1950
|
+
const a = +(((x = (o.getAttribute("style") || "").match(/level(\d+)/i)) == null ? void 0 : x[1]) || 1), h = Array.from(o.querySelectorAll("span")).find(
|
|
1951
1951
|
(w) => /mso-list\s*:\s*ignore/i.test(w.getAttribute("style") || "")
|
|
1952
|
-
),
|
|
1953
|
-
for (h && h.remove(); l.length && l[l.length - 1].level >
|
|
1954
|
-
if (!l.length || l[l.length - 1].level <
|
|
1955
|
-
const w =
|
|
1952
|
+
), p = h ? ((C = h.textContent) == null ? void 0 : C.trim()) || "" : (((S = o.textContent) == null ? void 0 : S.trim().match(/^\S{1,4}/)) || [""])[0], { ordered: m, style: g } = Ct(p);
|
|
1953
|
+
for (h && h.remove(); l.length && l[l.length - 1].level > a; ) l.pop();
|
|
1954
|
+
if (!l.length || l[l.length - 1].level < a) {
|
|
1955
|
+
const w = d.createElement(m ? "ol" : "ul");
|
|
1956
1956
|
if (m && g && (w.style.listStyleType = g), l.length) {
|
|
1957
1957
|
const k = l[l.length - 1].list;
|
|
1958
1958
|
(k.lastElementChild || k).appendChild(w);
|
|
1959
1959
|
} else
|
|
1960
|
-
|
|
1961
|
-
l.push({ list: w, level:
|
|
1960
|
+
n.parentNode.insertBefore(w, n);
|
|
1961
|
+
l.push({ list: w, level: a });
|
|
1962
1962
|
}
|
|
1963
|
-
const u =
|
|
1964
|
-
for (b && u.setAttribute("style", b),
|
|
1965
|
-
l[l.length - 1].list.appendChild(u),
|
|
1963
|
+
const u = d.createElement("li"), v = R(o), b = ["text-align", "direction", "unicode-bidi", "color", "font-size", "font-family", "background-color"].filter((w) => v[w]).map((w) => w + ":" + v[w]).join(";");
|
|
1964
|
+
for (b && u.setAttribute("style", b), o.getAttribute("dir") && u.setAttribute("dir", o.getAttribute("dir")); o.firstChild; ) u.appendChild(o.firstChild);
|
|
1965
|
+
l[l.length - 1].list.appendChild(u), o.remove();
|
|
1966
1966
|
});
|
|
1967
1967
|
});
|
|
1968
1968
|
}
|
|
1969
|
-
function
|
|
1970
|
-
|
|
1969
|
+
function Tt(d) {
|
|
1970
|
+
d.querySelectorAll('b[id^="docs-internal-guid"]').forEach((t) => {
|
|
1971
1971
|
for (; t.firstChild; ) t.parentNode.insertBefore(t.firstChild, t);
|
|
1972
1972
|
t.remove();
|
|
1973
1973
|
});
|
|
1974
1974
|
}
|
|
1975
|
-
function
|
|
1976
|
-
|
|
1975
|
+
function St(d) {
|
|
1976
|
+
d.querySelectorAll("table").forEach((t) => {
|
|
1977
1977
|
const e = t;
|
|
1978
|
-
|
|
1979
|
-
}),
|
|
1978
|
+
R(e)["border-collapse"] || (e.style.borderCollapse = "collapse");
|
|
1979
|
+
}), d.querySelectorAll("[align]").forEach((t) => {
|
|
1980
1980
|
const e = t, i = e.getAttribute("align").toLowerCase();
|
|
1981
1981
|
e.tagName.toLowerCase() === "table" ? i === "center" ? (e.style.marginLeft = e.style.marginLeft || "auto", e.style.marginRight = e.style.marginRight || "auto") : i === "right" ? e.style.marginLeft = e.style.marginLeft || "auto" : i === "left" && (e.style.marginRight = e.style.marginRight || "auto") : ["left", "right", "center", "justify"].includes(i) && (e.style.textAlign = e.style.textAlign || i, Array.from(e.children).forEach((s) => {
|
|
1982
1982
|
if (s.tagName.toLowerCase() !== "table") return;
|
|
1983
1983
|
const l = s;
|
|
1984
1984
|
i === "center" ? (l.style.marginLeft = l.style.marginLeft || "auto", l.style.marginRight = l.style.marginRight || "auto") : i === "right" ? l.style.marginLeft = l.style.marginLeft || "auto" : i === "left" && (l.style.marginRight = l.style.marginRight || "auto");
|
|
1985
1985
|
})), e.removeAttribute("align");
|
|
1986
|
-
}),
|
|
1986
|
+
}), d.querySelectorAll("center table").forEach((t) => {
|
|
1987
1987
|
const e = t;
|
|
1988
1988
|
e.style.marginLeft = e.style.marginLeft || "auto", e.style.marginRight = e.style.marginRight || "auto";
|
|
1989
|
-
}),
|
|
1989
|
+
}), d.querySelectorAll("[bgcolor]").forEach((t) => {
|
|
1990
1990
|
const e = t;
|
|
1991
1991
|
e.style.backgroundColor = e.style.backgroundColor || e.getAttribute("bgcolor"), e.removeAttribute("bgcolor");
|
|
1992
1992
|
});
|
|
1993
1993
|
}
|
|
1994
|
-
function Z(
|
|
1995
|
-
Array.from(
|
|
1994
|
+
function Z(d, t) {
|
|
1995
|
+
Array.from(d.childNodes).forEach((e) => {
|
|
1996
1996
|
if (e.nodeType === Node.COMMENT_NODE) {
|
|
1997
1997
|
e.remove();
|
|
1998
1998
|
return;
|
|
1999
1999
|
}
|
|
2000
2000
|
if (e.nodeType !== Node.ELEMENT_NODE) return;
|
|
2001
2001
|
const i = e, s = i.tagName.toLowerCase();
|
|
2002
|
-
if (!
|
|
2002
|
+
if (!bt.has(s)) {
|
|
2003
2003
|
if (s === "font") {
|
|
2004
2004
|
const r = t.createElement("span");
|
|
2005
2005
|
i.getAttribute("style") && r.setAttribute("style", i.getAttribute("style")), i.getAttribute("color") && (r.style.color = i.getAttribute("color")), i.getAttribute("face") && (r.style.fontFamily = i.getAttribute("face"));
|
|
2006
|
-
const
|
|
2007
|
-
if (
|
|
2006
|
+
const a = i.getAttribute("size");
|
|
2007
|
+
if (a && !r.style.fontSize) {
|
|
2008
2008
|
const h = {
|
|
2009
2009
|
1: "8pt",
|
|
2010
2010
|
2: "10pt",
|
|
@@ -2014,7 +2014,7 @@ function Z(p, t) {
|
|
|
2014
2014
|
6: "24pt",
|
|
2015
2015
|
7: "36pt"
|
|
2016
2016
|
};
|
|
2017
|
-
h[
|
|
2017
|
+
h[a] && (r.style.fontSize = h[a]);
|
|
2018
2018
|
}
|
|
2019
2019
|
for (; i.firstChild; ) r.appendChild(i.firstChild);
|
|
2020
2020
|
i.replaceWith(r), Z(r, t);
|
|
@@ -2024,10 +2024,10 @@ function Z(p, t) {
|
|
|
2024
2024
|
i.remove();
|
|
2025
2025
|
return;
|
|
2026
2026
|
}
|
|
2027
|
-
const l = /* @__PURE__ */ new Set([...
|
|
2027
|
+
const l = /* @__PURE__ */ new Set([...Q["*"] || [], ...Q[s] || []]);
|
|
2028
2028
|
if (Array.from(i.attributes).forEach((r) => {
|
|
2029
|
-
const
|
|
2030
|
-
|
|
2029
|
+
const a = r.name.toLowerCase();
|
|
2030
|
+
a !== "style" && !l.has(a) && i.removeAttribute(r.name);
|
|
2031
2031
|
}), s === "a") {
|
|
2032
2032
|
const r = i.getAttribute("href") || "";
|
|
2033
2033
|
/^(https?:|mailto:|tel:|#)/i.test(r) || i.removeAttribute("href");
|
|
@@ -2035,130 +2035,233 @@ function Z(p, t) {
|
|
|
2035
2035
|
if (s === "img") {
|
|
2036
2036
|
const r = i.getAttribute("src") || "";
|
|
2037
2037
|
if (!/^(https?:|data:image\/|blob:)/i.test(r)) {
|
|
2038
|
-
const
|
|
2039
|
-
|
|
2038
|
+
const a = t.createElement("span");
|
|
2039
|
+
a.textContent = "[local image — paste it separately]", a.setAttribute("style", "color:#a33;font-style:italic;font-size:12px"), i.replaceWith(a);
|
|
2040
2040
|
return;
|
|
2041
2041
|
}
|
|
2042
2042
|
}
|
|
2043
|
-
const
|
|
2044
|
-
for (const [r,
|
|
2045
|
-
|
|
2046
|
-
if (
|
|
2043
|
+
const n = R(i), o = [];
|
|
2044
|
+
for (const [r, a] of Object.entries(n))
|
|
2045
|
+
yt.has(r) && (/expression|javascript|url\s*\(\s*['"]?\s*file:/i.test(a) || r === "font-weight" && /^(400|normal)$/i.test(a) || r === "font-style" && /^normal$/i.test(a) || r === "text-decoration" && /^none$/i.test(a) || o.push(r + ":" + a));
|
|
2046
|
+
if (o.length ? i.setAttribute("style", o.join(";")) : i.removeAttribute("style"), i.removeAttribute("class"), Z(i, t), s === "span" && !i.attributes.length) {
|
|
2047
2047
|
for (; i.firstChild; ) i.parentNode.insertBefore(i.firstChild, i);
|
|
2048
2048
|
i.remove();
|
|
2049
2049
|
}
|
|
2050
2050
|
});
|
|
2051
2051
|
}
|
|
2052
|
-
function
|
|
2052
|
+
function Mt(d) {
|
|
2053
2053
|
const t = [], e = /<style[^>]*>([\s\S]*?)<\/style>/gi;
|
|
2054
2054
|
let i;
|
|
2055
|
-
for (; i = e.exec(
|
|
2055
|
+
for (; i = e.exec(d); ) {
|
|
2056
2056
|
let s = i[1].replace(/<!--|-->/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
2057
2057
|
s = s.replace(/@media[^{]*\{(?:[^{}]*\{[^{}]*\})*[^{}]*\}/gi, ""), s = s.replace(/@[\w-]+[^{]*\{[^{}]*\}/g, "");
|
|
2058
2058
|
let l;
|
|
2059
|
-
const
|
|
2060
|
-
for (; l =
|
|
2061
|
-
const
|
|
2062
|
-
const
|
|
2063
|
-
return
|
|
2059
|
+
const n = /([^{}]+)\{([^}]*)\}/g;
|
|
2060
|
+
for (; l = n.exec(s); ) {
|
|
2061
|
+
const o = l[2].split(";").map((r) => {
|
|
2062
|
+
const a = r.indexOf(":");
|
|
2063
|
+
return a < 1 ? null : [r.slice(0, a).trim().toLowerCase(), r.slice(a + 1).trim()];
|
|
2064
2064
|
}).filter((r) => !!r && !!r[1]);
|
|
2065
|
-
|
|
2065
|
+
o.length && l[1].split(",").map((r) => r.trim()).filter((r) => r && !r.startsWith("@")).forEach((r) => t.push({ sel: r, decls: o }));
|
|
2066
2066
|
}
|
|
2067
2067
|
}
|
|
2068
2068
|
return t;
|
|
2069
2069
|
}
|
|
2070
|
-
function
|
|
2070
|
+
function Et(d, t) {
|
|
2071
2071
|
if (!t.length) return;
|
|
2072
2072
|
const e = /* @__PURE__ */ new Map();
|
|
2073
2073
|
t.forEach(({ sel: i, decls: s }) => {
|
|
2074
2074
|
let l;
|
|
2075
2075
|
try {
|
|
2076
|
-
l =
|
|
2076
|
+
l = d.querySelectorAll(i);
|
|
2077
2077
|
} catch {
|
|
2078
2078
|
return;
|
|
2079
2079
|
}
|
|
2080
|
-
l.forEach((
|
|
2081
|
-
let
|
|
2082
|
-
|
|
2083
|
-
|
|
2080
|
+
l.forEach((n) => {
|
|
2081
|
+
let o = e.get(n);
|
|
2082
|
+
o || (o = {}, e.set(n, o)), s.forEach(([r, a]) => {
|
|
2083
|
+
o[r] = a;
|
|
2084
2084
|
});
|
|
2085
2085
|
});
|
|
2086
2086
|
}), e.forEach((i, s) => {
|
|
2087
|
-
const l =
|
|
2087
|
+
const l = R(s), n = s.hasAttribute("dir"), o = s.hasAttribute("align"), r = Object.entries(i).filter(([p]) => !(p in l || (p === "direction" || p === "unicode-bidi") && n || p === "text-align" && (o || n) || (p === "background" || p === "background-color") && s.hasAttribute("bgcolor")));
|
|
2088
2088
|
if (!r.length) return;
|
|
2089
|
-
const
|
|
2090
|
-
s.setAttribute("style", h ?
|
|
2089
|
+
const a = r.map(([p, m]) => p + ":" + m).join(";"), h = s.getAttribute("style");
|
|
2090
|
+
s.setAttribute("style", h ? a + ";" + h : a);
|
|
2091
2091
|
});
|
|
2092
2092
|
}
|
|
2093
|
-
function
|
|
2094
|
-
return
|
|
2093
|
+
function st(d) {
|
|
2094
|
+
return d.replace(/[ﭐ-﷿ﹰ-ﻼ]+/g, (t) => t.normalize("NFKC"));
|
|
2095
2095
|
}
|
|
2096
|
-
function
|
|
2097
|
-
const t =
|
|
2096
|
+
function Lt(d) {
|
|
2097
|
+
const t = d.createTreeWalker(d.body, NodeFilter.SHOW_TEXT, null);
|
|
2098
2098
|
let e;
|
|
2099
2099
|
for (; e = t.nextNode(); )
|
|
2100
|
-
/[ﭐ-﷿ﹰ-ﻼ]/.test(e.nodeValue || "") && (e.nodeValue =
|
|
2100
|
+
/[ﭐ-﷿ﹰ-ﻼ]/.test(e.nodeValue || "") && (e.nodeValue = st(e.nodeValue || ""));
|
|
2101
2101
|
}
|
|
2102
|
-
function
|
|
2103
|
-
const e =
|
|
2104
|
-
|
|
2102
|
+
function Ht(d, t = "ltr") {
|
|
2103
|
+
const e = Mt(d), i = new DOMParser().parseFromString(xt(d), "text/html");
|
|
2104
|
+
Et(i, e), /class="?Mso|mso-|urn:schemas-microsoft-com/i.test(i.body.innerHTML) && wt(i), Tt(i), St(i), Z(i.body, i), Lt(i);
|
|
2105
2105
|
const s = (l) => {
|
|
2106
|
-
var
|
|
2107
|
-
return l && l.tagName === "P" && !((
|
|
2106
|
+
var n;
|
|
2107
|
+
return l && l.tagName === "P" && !((n = l.textContent) != null && n.trim()) && !l.querySelector("img,table");
|
|
2108
2108
|
};
|
|
2109
2109
|
for (; s(i.body.firstElementChild); ) i.body.firstElementChild.remove();
|
|
2110
2110
|
for (; s(i.body.lastElementChild); ) i.body.lastElementChild.remove();
|
|
2111
2111
|
return i.body.innerHTML.trim();
|
|
2112
2112
|
}
|
|
2113
|
-
function
|
|
2114
|
-
const t =
|
|
2113
|
+
function kt(d) {
|
|
2114
|
+
const t = st(d).replace(/\r/g, ""), e = (i) => i.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
2115
2115
|
return /\n/.test(t) ? t.split(/\n{2,}/).map((i) => `<p dir="auto">${e(i).replace(/\n/g, "<br>") || "<br>"}</p>`).join("") : e(t);
|
|
2116
2116
|
}
|
|
2117
|
-
|
|
2118
|
-
|
|
2117
|
+
const At = 10 * 1024 * 1024, lt = /^(https?:|data:image\/|blob:)/i;
|
|
2118
|
+
function G(d, t) {
|
|
2119
|
+
const e = [], i = "{\\" + t;
|
|
2120
|
+
let s = 0;
|
|
2121
|
+
for (; (s = d.indexOf(i, s)) !== -1; ) {
|
|
2122
|
+
const l = d[s + i.length];
|
|
2123
|
+
if (l && /[a-z0-9]/i.test(l)) {
|
|
2124
|
+
s += i.length;
|
|
2125
|
+
continue;
|
|
2126
|
+
}
|
|
2127
|
+
let n = 0, o = s;
|
|
2128
|
+
for (; o < d.length; o++) {
|
|
2129
|
+
const r = d[o];
|
|
2130
|
+
if (r === "\\") {
|
|
2131
|
+
o++;
|
|
2132
|
+
continue;
|
|
2133
|
+
}
|
|
2134
|
+
if (r === "{") n++;
|
|
2135
|
+
else if (r === "}" && (n--, !n))
|
|
2136
|
+
break;
|
|
2137
|
+
}
|
|
2138
|
+
e.push({ start: s, end: o + 1, body: d.slice(s + i.length, o) }), s = o + 1;
|
|
2139
|
+
}
|
|
2140
|
+
return e;
|
|
2141
|
+
}
|
|
2142
|
+
function It(d) {
|
|
2143
|
+
const t = new Uint8Array(d.length / 2);
|
|
2144
|
+
for (let e = 0; e < t.length; e++) t[e] = parseInt(d.substr(e * 2, 2), 16);
|
|
2145
|
+
return t;
|
|
2146
|
+
}
|
|
2147
|
+
function F(d) {
|
|
2148
|
+
let t = "";
|
|
2149
|
+
for (let e = 0; e < d.length; e++) t += String.fromCharCode(d[e]);
|
|
2150
|
+
return btoa(t);
|
|
2151
|
+
}
|
|
2152
|
+
function Y(d, t) {
|
|
2153
|
+
t: for (let e = 0; e + t.length <= d.length; e++) {
|
|
2154
|
+
for (let i = 0; i < t.length; i++) if (d[e + i] !== t[i]) continue t;
|
|
2155
|
+
return e;
|
|
2156
|
+
}
|
|
2157
|
+
return -1;
|
|
2158
|
+
}
|
|
2159
|
+
const qt = [137, 80, 78, 71], Bt = [255, 216, 255];
|
|
2160
|
+
function Nt(d) {
|
|
2161
|
+
let t = null;
|
|
2162
|
+
if (/\\pngblip/.test(d) ? t = "image/png" : /\\jpegblip/.test(d) ? t = "image/jpeg" : (/\\wmetafile\d*/.test(d) || /\\emfblip/.test(d)) && (t = "metafile"), !t) return null;
|
|
2163
|
+
let e = d.replace(/\{[^{}]*\}/g, "").replace(/\\[a-z]+-?\d*\s?/gi, "").replace(/[^0-9a-fA-F]/g, "");
|
|
2164
|
+
if (e.length % 2 && (e = e.slice(0, -1)), !e) return null;
|
|
2165
|
+
const i = It(e);
|
|
2166
|
+
if (t === "metafile") {
|
|
2167
|
+
const s = Y(i, qt);
|
|
2168
|
+
if (s >= 0) return "data:image/png;base64," + F(i.slice(s));
|
|
2169
|
+
const l = Y(i, Bt);
|
|
2170
|
+
return l >= 0 ? "data:image/jpeg;base64," + F(i.slice(l)) : null;
|
|
2171
|
+
}
|
|
2172
|
+
return "data:" + t + ";base64," + F(i);
|
|
2173
|
+
}
|
|
2174
|
+
function Zt(d) {
|
|
2175
|
+
if (!d || d.indexOf("\\pict") === -1) return [];
|
|
2176
|
+
let t = d;
|
|
2177
|
+
G(d, "nonshppict").reverse().forEach((i) => {
|
|
2178
|
+
t = t.slice(0, i.start) + t.slice(i.end);
|
|
2179
|
+
});
|
|
2180
|
+
let e = At;
|
|
2181
|
+
return G(t, "pict").map((i) => {
|
|
2182
|
+
if (e <= 0) return null;
|
|
2183
|
+
const s = Nt(i.body);
|
|
2184
|
+
return s && (e -= s.length * 0.75), s;
|
|
2185
|
+
});
|
|
2186
|
+
}
|
|
2187
|
+
function nt(d, t) {
|
|
2188
|
+
if (!d || !t.length) return { html: d, injected: [] };
|
|
2189
|
+
const e = [];
|
|
2190
|
+
let i = 0;
|
|
2191
|
+
return { html: d.replace(/<img\b[^>]*>/gi, (l) => {
|
|
2192
|
+
const n = (l.match(/\ssrc\s*=\s*["']?([^"'\s>]+)/i) || [])[1] || "";
|
|
2193
|
+
if (lt.test(n)) return l;
|
|
2194
|
+
const o = t[i++];
|
|
2195
|
+
return o ? (e.push(o), /\ssrc\s*=\s*["']/i.test(l) ? l.replace(/(\ssrc\s*=\s*)(["'])[^"']*\2/i, '$1"' + o + '"') : l.replace(/(\ssrc\s*=\s*)[^\s>]+/i, '$1"' + o + '"')) : l;
|
|
2196
|
+
}), injected: e };
|
|
2197
|
+
}
|
|
2198
|
+
function Pt(d, t) {
|
|
2199
|
+
return !d || !t ? { html: d, injected: [] } : nt(d, Zt(t));
|
|
2200
|
+
}
|
|
2201
|
+
function Rt(d) {
|
|
2202
|
+
const t = d.match(/<img\b[^>]*>/gi);
|
|
2203
|
+
return t ? t.filter((e) => {
|
|
2204
|
+
const i = (e.match(/\ssrc\s*=\s*["']?([^"'\s>]+)/i) || [])[1] || "";
|
|
2205
|
+
return !lt.test(i);
|
|
2206
|
+
}).length : 0;
|
|
2207
|
+
}
|
|
2208
|
+
function Dt(d, t) {
|
|
2209
|
+
const e = d.match(/^data:([^;,]+);base64,(.*)$/);
|
|
2210
|
+
if (!e) return null;
|
|
2211
|
+
const i = (e[1].split("/")[1] || "png").replace(/[^a-z0-9]/gi, "") || "png";
|
|
2212
|
+
try {
|
|
2213
|
+
const s = atob(e[2]), l = new Uint8Array(s.length);
|
|
2214
|
+
for (let n = 0; n < s.length; n++) l[n] = s.charCodeAt(n);
|
|
2215
|
+
return new File([l], t + "." + (i === "jpeg" ? "jpg" : i), { type: e[1] });
|
|
2216
|
+
} catch {
|
|
2217
|
+
return null;
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
function Ft(d) {
|
|
2221
|
+
const t = new DataView(d), e = /* @__PURE__ */ new Map();
|
|
2119
2222
|
let i = -1;
|
|
2120
|
-
for (let
|
|
2121
|
-
if (t.getUint32(
|
|
2122
|
-
i =
|
|
2223
|
+
for (let o = d.byteLength - 22; o >= Math.max(0, d.byteLength - 22 - 65535); o--)
|
|
2224
|
+
if (t.getUint32(o, !0) === 101010256) {
|
|
2225
|
+
i = o;
|
|
2123
2226
|
break;
|
|
2124
2227
|
}
|
|
2125
2228
|
if (i < 0) throw new Error("EOCD not found");
|
|
2126
2229
|
const s = t.getUint16(i + 10, !0);
|
|
2127
2230
|
let l = t.getUint32(i + 16, !0);
|
|
2128
|
-
const
|
|
2129
|
-
for (let
|
|
2130
|
-
const r = t.getUint16(l + 10, !0),
|
|
2131
|
-
e.set(u, { name: u, method: r, compSize:
|
|
2231
|
+
const n = new TextDecoder();
|
|
2232
|
+
for (let o = 0; o < s && t.getUint32(l, !0) === 33639248; o++) {
|
|
2233
|
+
const r = t.getUint16(l + 10, !0), a = t.getUint32(l + 20, !0), h = t.getUint16(l + 28, !0), p = t.getUint16(l + 30, !0), m = t.getUint16(l + 32, !0), g = t.getUint32(l + 42, !0), u = n.decode(new Uint8Array(d, l + 46, h));
|
|
2234
|
+
e.set(u, { name: u, method: r, compSize: a, localOffset: g }), l += 46 + h + p + m;
|
|
2132
2235
|
}
|
|
2133
2236
|
return e;
|
|
2134
2237
|
}
|
|
2135
|
-
async function
|
|
2136
|
-
const e = new DataView(
|
|
2238
|
+
async function K(d, t) {
|
|
2239
|
+
const e = new DataView(d, t.localOffset);
|
|
2137
2240
|
if (e.getUint32(0, !0) !== 67324752) throw new Error("Bad local header");
|
|
2138
|
-
const i = e.getUint16(26, !0), s = e.getUint16(28, !0), l = t.localOffset + 30 + i + s,
|
|
2139
|
-
if (t.method === 0) return
|
|
2241
|
+
const i = e.getUint16(26, !0), s = e.getUint16(28, !0), l = t.localOffset + 30 + i + s, n = new Uint8Array(d.slice(l, l + t.compSize));
|
|
2242
|
+
if (t.method === 0) return n;
|
|
2140
2243
|
if (t.method !== 8) throw new Error("Unsupported compression method " + t.method);
|
|
2141
|
-
const
|
|
2142
|
-
return new Uint8Array(await new Response(
|
|
2244
|
+
const o = new Blob([n]).stream().pipeThrough(new DecompressionStream("deflate-raw"));
|
|
2245
|
+
return new Uint8Array(await new Response(o).arrayBuffer());
|
|
2143
2246
|
}
|
|
2144
|
-
const
|
|
2145
|
-
let e =
|
|
2247
|
+
const J = (d) => d.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """), P = (d, t) => Array.from(d.children).filter((e) => e.localName === t), M = (d, ...t) => {
|
|
2248
|
+
let e = d;
|
|
2146
2249
|
for (const i of t) {
|
|
2147
2250
|
if (!e) return null;
|
|
2148
2251
|
e = Array.from(e.children).find((s) => s.localName === i) || null;
|
|
2149
2252
|
}
|
|
2150
2253
|
return e;
|
|
2151
|
-
}, T = (
|
|
2152
|
-
if (!
|
|
2153
|
-
for (const e of Array.from(
|
|
2254
|
+
}, T = (d, t = "val") => {
|
|
2255
|
+
if (!d) return "";
|
|
2256
|
+
for (const e of Array.from(d.attributes))
|
|
2154
2257
|
if (e.localName === t) return e.value;
|
|
2155
2258
|
return "";
|
|
2156
|
-
}, B = (
|
|
2157
|
-
const e =
|
|
2259
|
+
}, B = (d, t) => {
|
|
2260
|
+
const e = d ? M(d, t) : null;
|
|
2158
2261
|
if (!e) return !1;
|
|
2159
2262
|
const i = T(e);
|
|
2160
2263
|
return i !== "false" && i !== "0";
|
|
2161
|
-
},
|
|
2264
|
+
}, tt = {
|
|
2162
2265
|
yellow: "#FFFF00",
|
|
2163
2266
|
green: "#00FF00",
|
|
2164
2267
|
cyan: "#00FFFF",
|
|
@@ -2175,7 +2278,7 @@ const G = (p) => p.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, "&
|
|
|
2175
2278
|
lightGray: "#D3D3D3",
|
|
2176
2279
|
black: "#000000",
|
|
2177
2280
|
white: "#FFFFFF"
|
|
2178
|
-
},
|
|
2281
|
+
}, Ot = {
|
|
2179
2282
|
png: "image/png",
|
|
2180
2283
|
jpg: "image/jpeg",
|
|
2181
2284
|
jpeg: "image/jpeg",
|
|
@@ -2183,13 +2286,13 @@ const G = (p) => p.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, "&
|
|
|
2183
2286
|
bmp: "image/bmp",
|
|
2184
2287
|
webp: "image/webp"
|
|
2185
2288
|
};
|
|
2186
|
-
function
|
|
2289
|
+
function $t(d) {
|
|
2187
2290
|
let t = "";
|
|
2188
|
-
for (let e = 0; e <
|
|
2189
|
-
t += String.fromCharCode(...
|
|
2291
|
+
for (let e = 0; e < d.length; e += 32768)
|
|
2292
|
+
t += String.fromCharCode(...d.subarray(e, e + 32768));
|
|
2190
2293
|
return btoa(t);
|
|
2191
2294
|
}
|
|
2192
|
-
class
|
|
2295
|
+
class _t {
|
|
2193
2296
|
constructor(t, e, i) {
|
|
2194
2297
|
this.rels = t, this.images = e, this.numFmt = i;
|
|
2195
2298
|
}
|
|
@@ -2200,12 +2303,12 @@ class Ht {
|
|
|
2200
2303
|
};
|
|
2201
2304
|
for (const l of Array.from(t.children))
|
|
2202
2305
|
if (l.localName === "p") {
|
|
2203
|
-
const
|
|
2204
|
-
if (
|
|
2205
|
-
const
|
|
2206
|
-
for (; i.length >
|
|
2207
|
-
for (i.length ===
|
|
2208
|
-
e += `<${
|
|
2306
|
+
const n = this.paraList(l);
|
|
2307
|
+
if (n) {
|
|
2308
|
+
const o = n.ilvl + 1;
|
|
2309
|
+
for (; i.length > o; ) e += `</${i.pop()}>`;
|
|
2310
|
+
for (i.length === o && i[o - 1] !== n.type && (e += `</${i.pop()}>`); i.length < o; )
|
|
2311
|
+
e += `<${n.type}>`, i.push(n.type);
|
|
2209
2312
|
e += `<li>${this.runsOf(l) || "<br>"}</li>`;
|
|
2210
2313
|
continue;
|
|
2211
2314
|
}
|
|
@@ -2214,22 +2317,22 @@ class Ht {
|
|
|
2214
2317
|
return s(0), e || "<p><br></p>";
|
|
2215
2318
|
}
|
|
2216
2319
|
paraList(t) {
|
|
2217
|
-
const e =
|
|
2320
|
+
const e = M(t, "pPr", "numPr");
|
|
2218
2321
|
if (!e) return null;
|
|
2219
|
-
const i = T(
|
|
2322
|
+
const i = T(M(e, "numId"));
|
|
2220
2323
|
if (!i || i === "0") return null;
|
|
2221
|
-
const s = parseInt(T(
|
|
2324
|
+
const s = parseInt(T(M(e, "ilvl")) || "0", 10) || 0;
|
|
2222
2325
|
return { type: this.numFmt.get(i) || "ul", ilvl: Math.min(s, 8) };
|
|
2223
2326
|
}
|
|
2224
2327
|
convertPara(t) {
|
|
2225
|
-
const e =
|
|
2328
|
+
const e = M(t, "pPr"), i = T(M(t, "pPr", "pStyle"));
|
|
2226
2329
|
let s = "p";
|
|
2227
2330
|
const l = /^Heading([1-6])$/i.exec(i);
|
|
2228
2331
|
l ? s = "h" + l[1] : /^Title$/i.test(i) && (s = "h1");
|
|
2229
|
-
const
|
|
2230
|
-
|
|
2231
|
-
const r = this.runsOf(t),
|
|
2232
|
-
return `<${s}${
|
|
2332
|
+
const n = [], o = T(M(t, "pPr", "jc"));
|
|
2333
|
+
o === "center" ? n.push("text-align:center") : o === "right" || o === "end" ? n.push("text-align:right") : (o === "both" || o === "distribute") && n.push("text-align:justify"), e && M(e, "bidi") && n.push("direction:rtl");
|
|
2334
|
+
const r = this.runsOf(t), a = n.length ? ` style="${n.join(";")}"` : "";
|
|
2335
|
+
return `<${s}${a}>${r || "<br>"}</${s}>`;
|
|
2233
2336
|
}
|
|
2234
2337
|
runsOf(t) {
|
|
2235
2338
|
let e = "";
|
|
@@ -2239,88 +2342,88 @@ class Ht {
|
|
|
2239
2342
|
let s = this.rels.get(T(i, "id")) || "";
|
|
2240
2343
|
const l = T(i, "anchor");
|
|
2241
2344
|
!s && l && (s = "#" + l);
|
|
2242
|
-
const
|
|
2243
|
-
e += s ? `<a href="${
|
|
2345
|
+
const n = this.runsOf(i);
|
|
2346
|
+
e += s ? `<a href="${J(s)}">${n}</a>` : n;
|
|
2244
2347
|
} else (i.localName === "smartTag" || i.localName === "ins") && (e += this.runsOf(i));
|
|
2245
2348
|
return e;
|
|
2246
2349
|
}
|
|
2247
2350
|
convertRun(t) {
|
|
2248
|
-
const e =
|
|
2351
|
+
const e = M(t, "rPr");
|
|
2249
2352
|
let i = "";
|
|
2250
|
-
for (const
|
|
2251
|
-
|
|
2353
|
+
for (const p of Array.from(t.children))
|
|
2354
|
+
p.localName === "t" ? i += J(p.textContent || "") : p.localName === "br" || p.localName === "cr" ? i += "<br>" : p.localName === "tab" ? i += " " : (p.localName === "drawing" || p.localName === "pict" || p.localName === "object") && (i += this.convertImage(p));
|
|
2252
2355
|
if (!i) return "";
|
|
2253
|
-
const s = [], l = T(e ?
|
|
2356
|
+
const s = [], l = T(e ? M(e, "color") : null);
|
|
2254
2357
|
l && l !== "auto" && s.push("color:#" + l);
|
|
2255
|
-
const
|
|
2256
|
-
|
|
2257
|
-
const
|
|
2258
|
-
|
|
2259
|
-
const r = e ?
|
|
2260
|
-
|
|
2261
|
-
const h = T(e ?
|
|
2358
|
+
const n = T(e ? M(e, "highlight") : null);
|
|
2359
|
+
n && tt[n] && s.push("background-color:" + tt[n]);
|
|
2360
|
+
const o = parseFloat(T(e ? M(e, "sz") : null));
|
|
2361
|
+
o && s.push("font-size:" + Math.round(o / 2 * (4 / 3)) + "px");
|
|
2362
|
+
const r = e ? M(e, "rFonts") : null, a = T(r, "ascii") || T(r, "cs");
|
|
2363
|
+
a && s.push(`font-family:'${a}'`), s.length && (i = `<span style="${s.join(";")}">${i}</span>`), B(e, "b") && (i = `<strong>${i}</strong>`), B(e, "i") && (i = `<em>${i}</em>`), B(e, "u") && T(M(e, "u")) !== "none" && (i = `<u>${i}</u>`), B(e, "strike") && (i = `<s>${i}</s>`);
|
|
2364
|
+
const h = T(e ? M(e, "vertAlign") : null);
|
|
2262
2365
|
return h === "superscript" ? i = `<sup>${i}</sup>` : h === "subscript" && (i = `<sub>${i}</sub>`), i;
|
|
2263
2366
|
}
|
|
2264
2367
|
convertImage(t) {
|
|
2265
2368
|
let e = "", i = 0;
|
|
2266
|
-
const s = (
|
|
2267
|
-
if (
|
|
2268
|
-
const r = parseFloat(
|
|
2369
|
+
const s = (o) => {
|
|
2370
|
+
if (o.localName === "blip" && (e = e || T(o, "embed") || T(o, "link")), o.localName === "imagedata" && (e = e || T(o, "id")), o.localName === "extent") {
|
|
2371
|
+
const r = parseFloat(o.getAttribute("cx") || "0");
|
|
2269
2372
|
r && (i = Math.round(r / 9525));
|
|
2270
2373
|
}
|
|
2271
|
-
for (const r of Array.from(
|
|
2374
|
+
for (const r of Array.from(o.children)) s(r);
|
|
2272
2375
|
};
|
|
2273
2376
|
if (s(t), !e) return "";
|
|
2274
2377
|
const l = this.images.get(e);
|
|
2275
2378
|
if (!l) return "";
|
|
2276
|
-
const
|
|
2277
|
-
return `<img src="${l}" alt=""${
|
|
2379
|
+
const n = i ? ` width="${i}"` : "";
|
|
2380
|
+
return `<img src="${l}" alt=""${n}>`;
|
|
2278
2381
|
}
|
|
2279
2382
|
convertTable(t) {
|
|
2280
2383
|
let e = '<table style="border-collapse:collapse;width:100%"><tbody>';
|
|
2281
|
-
for (const i of
|
|
2384
|
+
for (const i of P(t, "tr")) {
|
|
2282
2385
|
e += "<tr>";
|
|
2283
|
-
for (const s of
|
|
2284
|
-
const l = parseInt(T(
|
|
2285
|
-
let
|
|
2386
|
+
for (const s of P(i, "tc")) {
|
|
2387
|
+
const l = parseInt(T(M(s, "tcPr", "gridSpan")) || "1", 10) || 1, n = l > 1 ? ` colspan="${l}"` : "";
|
|
2388
|
+
let o = "";
|
|
2286
2389
|
for (const r of Array.from(s.children))
|
|
2287
|
-
r.localName === "p" ?
|
|
2288
|
-
e += `<td style="border:1px solid #b9c2cc"${
|
|
2390
|
+
r.localName === "p" ? o += this.convertPara(r) : r.localName === "tbl" && (o += this.convertTable(r));
|
|
2391
|
+
e += `<td style="border:1px solid #b9c2cc"${n}>${o || "<br>"}</td>`;
|
|
2289
2392
|
}
|
|
2290
2393
|
e += "</tr>";
|
|
2291
2394
|
}
|
|
2292
2395
|
return e + "</tbody></table>";
|
|
2293
2396
|
}
|
|
2294
2397
|
}
|
|
2295
|
-
async function
|
|
2296
|
-
const t =
|
|
2398
|
+
async function zt(d) {
|
|
2399
|
+
const t = d instanceof ArrayBuffer ? d : await d.arrayBuffer(), e = Ft(t), i = new TextDecoder(), s = async (u) => {
|
|
2297
2400
|
const v = e.get(u);
|
|
2298
|
-
return v ? new DOMParser().parseFromString(i.decode(await
|
|
2299
|
-
}, l = await s("word/document.xml"),
|
|
2300
|
-
let
|
|
2301
|
-
if (
|
|
2302
|
-
for (const u of Array.from(
|
|
2401
|
+
return v ? new DOMParser().parseFromString(i.decode(await K(t, v)), "application/xml") : null;
|
|
2402
|
+
}, l = await s("word/document.xml"), n = l == null ? void 0 : l.getElementsByTagName("*");
|
|
2403
|
+
let o = null;
|
|
2404
|
+
if (n) {
|
|
2405
|
+
for (const u of Array.from(n))
|
|
2303
2406
|
if (u.localName === "body") {
|
|
2304
|
-
|
|
2407
|
+
o = u;
|
|
2305
2408
|
break;
|
|
2306
2409
|
}
|
|
2307
2410
|
}
|
|
2308
|
-
if (!
|
|
2309
|
-
const r = /* @__PURE__ */ new Map(),
|
|
2411
|
+
if (!o) throw new Error("word/document.xml missing or invalid");
|
|
2412
|
+
const r = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map(), h = await s("word/_rels/document.xml.rels");
|
|
2310
2413
|
if (h)
|
|
2311
2414
|
for (const u of Array.from(h.getElementsByTagName("*"))) {
|
|
2312
2415
|
if (u.localName !== "Relationship") continue;
|
|
2313
2416
|
const v = u.getAttribute("Id") || "", b = u.getAttribute("Target") || "", x = u.getAttribute("Type") || "";
|
|
2314
|
-
/hyperlink/i.test(x) ? r.set(v, b) : /image/i.test(x) &&
|
|
2417
|
+
/hyperlink/i.test(x) ? r.set(v, b) : /image/i.test(x) && a.set(v, b);
|
|
2315
2418
|
}
|
|
2316
|
-
const
|
|
2317
|
-
for (const [u, v] of
|
|
2419
|
+
const p = /* @__PURE__ */ new Map();
|
|
2420
|
+
for (const [u, v] of a) {
|
|
2318
2421
|
const b = v.startsWith("/") ? v.slice(1) : "word/" + v.replace(/^\.\//, ""), x = e.get(b);
|
|
2319
2422
|
if (!x) continue;
|
|
2320
|
-
const C = (b.split(".").pop() || "").toLowerCase(),
|
|
2321
|
-
if (
|
|
2423
|
+
const C = (b.split(".").pop() || "").toLowerCase(), S = Ot[C];
|
|
2424
|
+
if (S)
|
|
2322
2425
|
try {
|
|
2323
|
-
|
|
2426
|
+
p.set(u, `data:${S};base64,${$t(await K(t, x))}`);
|
|
2324
2427
|
} catch {
|
|
2325
2428
|
}
|
|
2326
2429
|
}
|
|
@@ -2329,83 +2432,83 @@ async function kt(p) {
|
|
|
2329
2432
|
const u = /* @__PURE__ */ new Map(), v = Array.from(g.getElementsByTagName("*"));
|
|
2330
2433
|
for (const b of v) {
|
|
2331
2434
|
if (b.localName !== "abstractNum") continue;
|
|
2332
|
-
const x = T(b, "abstractNumId"), C =
|
|
2333
|
-
u.set(x,
|
|
2435
|
+
const x = T(b, "abstractNumId"), C = P(b, "lvl").find((w) => T(w, "ilvl") === "0") || P(b, "lvl")[0], S = C ? T(M(C, "numFmt")) : "";
|
|
2436
|
+
u.set(x, S === "bullet" ? "ul" : "ol");
|
|
2334
2437
|
}
|
|
2335
2438
|
for (const b of v) {
|
|
2336
2439
|
if (b.localName !== "num") continue;
|
|
2337
|
-
const x = T(b, "numId"), C = T(
|
|
2440
|
+
const x = T(b, "numId"), C = T(M(b, "abstractNumId"));
|
|
2338
2441
|
m.set(x, u.get(C) || "ul");
|
|
2339
2442
|
}
|
|
2340
2443
|
}
|
|
2341
|
-
return new
|
|
2444
|
+
return new _t(r, p, m).convertBody(o);
|
|
2342
2445
|
}
|
|
2343
|
-
const
|
|
2446
|
+
const Ut = ["nw", "ne", "sw", "se"], O = ["img-left", "img-right", "img-top", "img-center"], $ = {
|
|
2344
2447
|
"img-left": "tplimgleft",
|
|
2345
2448
|
"img-right": "tplimgright",
|
|
2346
2449
|
"img-top": "tplimgtop",
|
|
2347
2450
|
"img-center": "tplimgcenter"
|
|
2348
|
-
},
|
|
2349
|
-
"img-left":
|
|
2350
|
-
"img-right":
|
|
2351
|
-
"img-top":
|
|
2352
|
-
"img-center":
|
|
2353
|
-
},
|
|
2354
|
-
let
|
|
2451
|
+
}, Wt = {
|
|
2452
|
+
"img-left": c.tplleft,
|
|
2453
|
+
"img-right": c.tplright,
|
|
2454
|
+
"img-top": c.tpltop,
|
|
2455
|
+
"img-center": c.tplcenter
|
|
2456
|
+
}, jt = ".tox,.pop,.tblctx,.imgctx,.selctx,.dlg";
|
|
2457
|
+
let E = null, A = null, _ = 0, et = !1;
|
|
2355
2458
|
function N() {
|
|
2356
|
-
clearTimeout(
|
|
2459
|
+
clearTimeout(_), A = null, E && E.classList.remove("show");
|
|
2357
2460
|
}
|
|
2358
|
-
function
|
|
2359
|
-
const t =
|
|
2461
|
+
function Vt(d) {
|
|
2462
|
+
const t = d.dataset.tip;
|
|
2360
2463
|
if (!t) return;
|
|
2361
|
-
A =
|
|
2362
|
-
const e =
|
|
2363
|
-
|
|
2364
|
-
if (A !==
|
|
2365
|
-
|
|
2366
|
-
const i =
|
|
2367
|
-
let
|
|
2368
|
-
|
|
2369
|
-
let
|
|
2370
|
-
|
|
2464
|
+
A = d, clearTimeout(_);
|
|
2465
|
+
const e = E && E.classList.contains("show") ? 60 : 350;
|
|
2466
|
+
_ = window.setTimeout(() => {
|
|
2467
|
+
if (A !== d || !document.contains(d)) return;
|
|
2468
|
+
E || (E = document.createElement("div"), E.className = "etip", document.body.appendChild(E)), E.textContent = t, E.classList.add("show");
|
|
2469
|
+
const i = d.getBoundingClientRect(), s = E.offsetWidth, l = E.offsetHeight;
|
|
2470
|
+
let n = i.left + i.width / 2 - s / 2;
|
|
2471
|
+
n = Math.max(6, Math.min(n, innerWidth - s - 6));
|
|
2472
|
+
let o = i.bottom + 7;
|
|
2473
|
+
o + l > innerHeight - 6 && (o = i.top - l - 7), E.style.left = n + "px", E.style.top = o + "px";
|
|
2371
2474
|
}, e);
|
|
2372
2475
|
}
|
|
2373
|
-
function
|
|
2374
|
-
|
|
2375
|
-
const t =
|
|
2376
|
-
if (!e || !e.closest(
|
|
2476
|
+
function Xt() {
|
|
2477
|
+
et || (et = !0, document.addEventListener("mouseover", (d) => {
|
|
2478
|
+
const t = d.target, e = t.closest ? t.closest("[title],[data-tip]") : null;
|
|
2479
|
+
if (!e || !e.closest(jt) || e.closest(".earea")) {
|
|
2377
2480
|
e !== A && N();
|
|
2378
2481
|
return;
|
|
2379
2482
|
}
|
|
2380
2483
|
const i = e.getAttribute("title");
|
|
2381
|
-
i && (e.dataset.tip = i, e.removeAttribute("title"), e.getAttribute("aria-label") || e.setAttribute("aria-label", i)), e !== A &&
|
|
2382
|
-
}), document.addEventListener("mouseout", (
|
|
2383
|
-
A && !A.contains(
|
|
2484
|
+
i && (e.dataset.tip = i, e.removeAttribute("title"), e.getAttribute("aria-label") || e.setAttribute("aria-label", i)), e !== A && Vt(e);
|
|
2485
|
+
}), document.addEventListener("mouseout", (d) => {
|
|
2486
|
+
A && !A.contains(d.relatedTarget) && N();
|
|
2384
2487
|
}), document.addEventListener("mousedown", N, !0), addEventListener("scroll", N, !0));
|
|
2385
2488
|
}
|
|
2386
|
-
const
|
|
2387
|
-
function
|
|
2388
|
-
for (const t of
|
|
2389
|
-
if (
|
|
2390
|
-
if (
|
|
2489
|
+
const Qt = /[\u0590-\u05FF\u0600-\u06FF\u0750-\u077F\u0780-\u07BF\u08A0-\u08FF\uFB1D-\uFB4F\uFB50-\uFDFF\uFE70-\uFEFF]/, Gt = new RegExp("\\p{L}", "u"), Yt = "p,div,li,td,th,blockquote,h1,h2,h3,h4,h5,h6,pre,figcaption";
|
|
2490
|
+
function Kt(d) {
|
|
2491
|
+
for (const t of d) {
|
|
2492
|
+
if (Qt.test(t)) return "rtl";
|
|
2493
|
+
if (Gt.test(t)) return "ltr";
|
|
2391
2494
|
}
|
|
2392
2495
|
return null;
|
|
2393
2496
|
}
|
|
2394
|
-
function
|
|
2497
|
+
function ot(d) {
|
|
2395
2498
|
let t = "";
|
|
2396
|
-
return
|
|
2499
|
+
return d.childNodes.forEach((e) => {
|
|
2397
2500
|
if (e.nodeType === Node.TEXT_NODE)
|
|
2398
2501
|
t += e.nodeValue || "";
|
|
2399
2502
|
else if (e.nodeType === Node.ELEMENT_NODE) {
|
|
2400
2503
|
const i = e, s = (i.getAttribute("dir") || "").toLowerCase();
|
|
2401
2504
|
if (s === "rtl" || s === "ltr") return;
|
|
2402
|
-
t +=
|
|
2505
|
+
t += ot(i);
|
|
2403
2506
|
}
|
|
2404
2507
|
}), t;
|
|
2405
2508
|
}
|
|
2406
2509
|
const I = class I {
|
|
2407
2510
|
constructor(t) {
|
|
2408
|
-
this.lang = "en", this.contentClass = "fable-content-" + I.instanceCounter++, this.contentStyleEl = null, this.savedRange = null, this.foreColor = "#000000", this.backColor = "#FACC15", this.openPop = null, this.
|
|
2511
|
+
this.lang = "en", this.contentClass = "fable-content-" + I.instanceCounter++, this.contentStyleEl = null, this.savedRange = null, this.foreColor = "#000000", this.backColor = "#FACC15", this.openPop = null, this.subStack = [], this.popAnchor = null, this.dlgOvl = null, this.tblActive = null, this.tblCorner = null, this.tblColBars = [], this.tblCtx = null, this.tblCellMark = null, this.tblOpMark = null, this.tblOpMarkKind = null, this.imgActive = null, this.imgHandles = [], this.imgCtx = null, this.imgHideTimer = null, this.phActive = null, this.phCtx = null, this.phUploadTarget = null, this.vidActive = null, this.vidCtx = null, this.vidHideTimer = null, this.vphActive = null, this.vphCtx = null, this.vphUploadTarget = null, this.selCtx = null, this.tbrMore = null, this.tbrExpanded = !1, this.codeActive = null, this.codeCtx = null, this.tplActive = null, this.tplCtx = null, this.revisions = [], this.revTimer = null, this.draftTimer = null, this.draftStorageKey = "", this.listeners = [], this.isDestroyed = !1, this.options = {
|
|
2409
2512
|
target: t.target,
|
|
2410
2513
|
language: t.language || "en",
|
|
2411
2514
|
height: t.height ?? 302,
|
|
@@ -2419,20 +2522,20 @@ const I = class I {
|
|
|
2419
2522
|
statusbar: t.statusbar ?? !0,
|
|
2420
2523
|
readonly: t.readonly ?? !1,
|
|
2421
2524
|
draftKey: t.draftKey ?? (typeof location < "u" ? location.pathname : "default"),
|
|
2422
|
-
fontFamilyFormats: t.fontFamilyFormats ??
|
|
2525
|
+
fontFamilyFormats: t.fontFamilyFormats ?? ht,
|
|
2423
2526
|
imageFileTypes: t.imageFileTypes ?? ["image/jpeg", "image/jpg", "image/png", "image/gif", "image/bmp", "image/webp"],
|
|
2424
2527
|
videoFileTypes: t.videoFileTypes ?? ["video/mp4", "video/webm", "video/ogg"]
|
|
2425
|
-
}, this.imageUploadHandler = t.imageUploadHandler, this.onImageUploadError = t.onImageUploadError, this.videoUploadHandler = t.videoUploadHandler, this.onVideoUploadError = t.onVideoUploadError, this.contentStyle = t.contentStyle, this.applyTheme(t), this.lang = this.options.language, this.draftStorageKey = "tmclone-draft:" + this.options.draftKey, this.initDOM(), this.bindEvents(), this.initUI(), this.recordRevision(), this.options.onReady(this);
|
|
2528
|
+
}, this.imageUploadHandler = t.imageUploadHandler, this.onImageUploadError = t.onImageUploadError, this.videoUploadHandler = t.videoUploadHandler, this.onVideoUploadError = t.onVideoUploadError, this.contentStyle = t.contentStyle, this.applyTheme(t), this.lang = this.options.language, this.draftStorageKey = "tmclone-draft:" + this.options.draftKey, this.initDOM(), this.bindEvents(), this.initUI(), this.recordRevision(), this.stampExistingImages(), this.options.onReady(this);
|
|
2426
2529
|
}
|
|
2427
2530
|
t(t) {
|
|
2428
|
-
const e =
|
|
2531
|
+
const e = D(this.lang)[t];
|
|
2429
2532
|
return typeof e == "string" ? e : e.join(",");
|
|
2430
2533
|
}
|
|
2431
2534
|
tArr(t) {
|
|
2432
|
-
return
|
|
2535
|
+
return D(this.lang)[t];
|
|
2433
2536
|
}
|
|
2434
2537
|
dir() {
|
|
2435
|
-
return
|
|
2538
|
+
return D(this.lang).dir;
|
|
2436
2539
|
}
|
|
2437
2540
|
/* ---------------------------------------------------------- DOM setup */
|
|
2438
2541
|
initDOM() {
|
|
@@ -2445,7 +2548,7 @@ const I = class I {
|
|
|
2445
2548
|
</span>
|
|
2446
2549
|
`, this.sbHelp = this.statusbar.querySelector(".mid"), this.sbWords = this.statusbar.querySelector(".words");
|
|
2447
2550
|
const e = this.statusbar.querySelector(".grip");
|
|
2448
|
-
this.bindGrip(e), this.shell.appendChild(this.menubar), this.shell.appendChild(this.toolbar), this.shell.appendChild(this.ed), this.shell.appendChild(this.statusbar), this.contentStyle && (this.contentStyleEl = document.createElement("style"), this.contentStyleEl.textContent = this.scopeContentStyle(this.contentStyle), this.shell.appendChild(this.contentStyleEl)), t.appendChild(this.shell),
|
|
2551
|
+
this.bindGrip(e), this.shell.appendChild(this.menubar), this.shell.appendChild(this.toolbar), this.shell.appendChild(this.ed), this.shell.appendChild(this.statusbar), this.contentStyle && (this.contentStyleEl = document.createElement("style"), this.contentStyleEl.textContent = this.scopeContentStyle(this.contentStyle), this.shell.appendChild(this.contentStyleEl)), t.appendChild(this.shell), Xt(), this.options.statusbar || (this.statusbar.style.display = "none"), this.imgInput = document.createElement("input"), this.imgInput.type = "file", this.imgInput.accept = this.options.imageFileTypes.join(","), this.imgInput.style.display = "none", t.appendChild(this.imgInput), this.vidInput = document.createElement("input"), this.vidInput.type = "file", this.vidInput.accept = this.options.videoFileTypes.join(","), this.vidInput.style.display = "none", t.appendChild(this.vidInput), this.docInput = document.createElement("input"), this.docInput.type = "file", this.docInput.accept = ".docx,application/vnd.openxmlformats-officedocument.wordprocessingml.document", this.docInput.style.display = "none", t.appendChild(this.docInput);
|
|
2449
2552
|
}
|
|
2450
2553
|
/** Theme options land as CSS variables on the document root rather than the editor
|
|
2451
2554
|
* shell, because dialogs, popups and floating context toolbars are appended to
|
|
@@ -2465,19 +2568,19 @@ const I = class I {
|
|
|
2465
2568
|
let e = 0, i = 0;
|
|
2466
2569
|
const s = (l) => {
|
|
2467
2570
|
e = l.clientY, i = this.ed.offsetHeight, l.preventDefault();
|
|
2468
|
-
const
|
|
2571
|
+
const n = (r) => {
|
|
2469
2572
|
this.ed.style.height = Math.max(120, i + r.clientY - e) + "px";
|
|
2470
|
-
},
|
|
2471
|
-
window.removeEventListener("mousemove",
|
|
2573
|
+
}, o = () => {
|
|
2574
|
+
window.removeEventListener("mousemove", n), window.removeEventListener("mouseup", o);
|
|
2472
2575
|
};
|
|
2473
|
-
window.addEventListener("mousemove",
|
|
2576
|
+
window.addEventListener("mousemove", n), window.addEventListener("mouseup", o);
|
|
2474
2577
|
};
|
|
2475
2578
|
t.addEventListener("mousedown", s), this.listeners.push(() => t.removeEventListener("mousedown", s));
|
|
2476
2579
|
}
|
|
2477
2580
|
/* ---------------------------------------------------------- event binding */
|
|
2478
2581
|
bindEvents() {
|
|
2479
2582
|
if (this.onDoc("mousedown", (t) => {
|
|
2480
|
-
this.openPop && !this.openPop.contains(t.target) && !this.popAnchor.contains(t.target) && !
|
|
2583
|
+
this.openPop && !this.openPop.contains(t.target) && !this.popAnchor.contains(t.target) && !this.subContains(t.target) && this.closePop();
|
|
2481
2584
|
}), this.onDoc("keydown", (t) => {
|
|
2482
2585
|
t.key === "Escape" && (this.closePop(), this.closeDlg());
|
|
2483
2586
|
}), this.onDoc("selectionchange", () => {
|
|
@@ -2488,52 +2591,54 @@ const I = class I {
|
|
|
2488
2591
|
}), this.on(this.ed, "keydown", (t) => {
|
|
2489
2592
|
t.altKey && t.key === "0" && (t.preventDefault(), this.helpDlg()), (t.key === "Delete" || t.key === "Backspace") && this.phActive && (t.preventDefault(), this.removeImgPlaceholder()), (t.key === "Delete" || t.key === "Backspace") && this.vphActive && (t.preventDefault(), this.removeVphPlaceholder()), t.key === "`" && !t.ctrlKey && !t.metaKey && !t.altKey && this.tryCodeTyping(t), t.key === "Enter" && !t.shiftKey && !t.ctrlKey && !t.metaKey && !t.altKey && this.tryExitBlockquote(t);
|
|
2490
2593
|
}), this.on(this.ed, "paste", (t) => this.handlePaste(t)), this.on(this.ed, "drop", (t) => {
|
|
2491
|
-
var l,
|
|
2594
|
+
var l, n, o, r;
|
|
2492
2595
|
t.preventDefault();
|
|
2493
2596
|
const e = t.target, i = (l = e.closest) == null ? void 0 : l.call(e, ".img-ph:not(.vid-ph)");
|
|
2494
2597
|
if (i && this.ed.contains(i) && !this.options.readonly) {
|
|
2495
|
-
const
|
|
2496
|
-
|
|
2598
|
+
const a = Array.from(((n = t.dataTransfer) == null ? void 0 : n.files) || []).find((h) => h.type.startsWith("image/"));
|
|
2599
|
+
a && this.readImageFileInto(a, i);
|
|
2497
2600
|
return;
|
|
2498
2601
|
}
|
|
2499
|
-
const s = (
|
|
2602
|
+
const s = (o = e.closest) == null ? void 0 : o.call(e, ".vid-ph");
|
|
2500
2603
|
if (s && this.ed.contains(s) && !this.options.readonly) {
|
|
2501
|
-
const
|
|
2502
|
-
|
|
2604
|
+
const a = Array.from(((r = t.dataTransfer) == null ? void 0 : r.files) || []).find((h) => h.type.startsWith("video/"));
|
|
2605
|
+
a && this.readVideoFileInto(a, s);
|
|
2503
2606
|
}
|
|
2504
2607
|
}), this.on(this.ed, "dragover", (t) => t.preventDefault()), this.on(this.ed, "mousedown", (t) => {
|
|
2505
|
-
var h,
|
|
2608
|
+
var h, p, m, g, u, v, b;
|
|
2506
2609
|
const e = t.target, i = (h = e.closest) == null ? void 0 : h.call(e, "table");
|
|
2507
2610
|
i && this.ed.contains(i) ? this.selectTableForResize(i) : this.clearTableHandles();
|
|
2508
|
-
const s = (
|
|
2611
|
+
const s = (p = e.closest) == null ? void 0 : p.call(e, ".img-ph:not(.vid-ph)");
|
|
2509
2612
|
s && this.ed.contains(s) && !this.options.readonly ? (t.preventDefault(), this.ed.focus(), this.selectImgPlaceholder(s)) : this.clearImgPlaceholderSel();
|
|
2510
2613
|
const l = (m = e.closest) == null ? void 0 : m.call(e, ".vid-ph");
|
|
2511
2614
|
l && this.ed.contains(l) && !this.options.readonly ? (t.preventDefault(), this.ed.focus(), this.selectVphPlaceholder(l)) : this.clearVphPlaceholderSel();
|
|
2512
|
-
const
|
|
2513
|
-
|
|
2514
|
-
const
|
|
2515
|
-
|
|
2615
|
+
const n = (g = e.closest) == null ? void 0 : g.call(e, ".tpl");
|
|
2616
|
+
n && this.ed.contains(n) && !this.options.readonly ? this.selectTemplate(n) : this.clearTplSel();
|
|
2617
|
+
const o = (u = e.closest) == null ? void 0 : u.call(e, "pre.code-block");
|
|
2618
|
+
o && this.ed.contains(o) && !this.options.readonly ? (t.preventDefault(), this.selectCodeEl(o)) : this.clearCodeSel();
|
|
2516
2619
|
const r = (v = e.closest) == null ? void 0 : v.call(e, "img");
|
|
2517
2620
|
r && this.ed.contains(r) && !this.options.readonly ? (t.preventDefault(), this.selectImage(r)) : this.clearImageHandles();
|
|
2518
|
-
const
|
|
2519
|
-
|
|
2621
|
+
const a = (b = e.closest) == null ? void 0 : b.call(e, "video, .video-embed");
|
|
2622
|
+
a && this.ed.contains(a) && !this.options.readonly ? (t.preventDefault(), this.selectVideo(a)) : this.clearVidHandles();
|
|
2520
2623
|
}), this.on(this.ed, "mouseover", (t) => {
|
|
2521
2624
|
var i, s;
|
|
2522
2625
|
if (this.options.readonly) return;
|
|
2523
2626
|
const e = (s = (i = t.target).closest) == null ? void 0 : s.call(i, "img");
|
|
2524
2627
|
e && this.ed.contains(e) && (this.cancelImgHide(), this.selectImage(e));
|
|
2525
2628
|
}), this.on(this.ed, "mouseout", (t) => {
|
|
2526
|
-
var s, l,
|
|
2629
|
+
var s, l, n, o;
|
|
2527
2630
|
const e = (l = (s = t.target).closest) == null ? void 0 : l.call(s, "img");
|
|
2528
2631
|
if (!e) return;
|
|
2529
2632
|
const i = t.relatedTarget;
|
|
2530
|
-
i && ((
|
|
2633
|
+
i && ((n = this.imgCtx) != null && n.contains(i) || this.imgHandles.some((r) => r.contains(i)) || ((o = i.closest) == null ? void 0 : o.call(i, "img")) === e) || this.scheduleImgHide();
|
|
2531
2634
|
}), this.on(this.ed, "scroll", () => {
|
|
2532
2635
|
this.positionTableHandles(), this.positionImageHandles(), this.positionImgPhCtx(), this.positionTplCtx(), this.positionVphCtx(), this.positionVidCtx(), this.positionCodeCtx();
|
|
2533
2636
|
}), this.onWin(
|
|
2534
2637
|
"scroll",
|
|
2535
|
-
() => {
|
|
2536
|
-
|
|
2638
|
+
(t) => {
|
|
2639
|
+
var s;
|
|
2640
|
+
const e = t.target;
|
|
2641
|
+
e instanceof Node && ((((s = this.openPop) == null ? void 0 : s.contains(e)) ?? !1) || this.subContains(e)) || this.closePop(), this.positionTableHandles(), this.positionImageHandles(), this.positionImgPhCtx(), this.positionTplCtx(), this.positionVphCtx(), this.positionVidCtx(), this.positionCodeCtx(), this.repositionSelToolbar();
|
|
2537
2642
|
},
|
|
2538
2643
|
!0
|
|
2539
2644
|
), this.onWin("resize", () => {
|
|
@@ -2553,11 +2658,7 @@ const I = class I {
|
|
|
2553
2658
|
}
|
|
2554
2659
|
const i = new FileReader();
|
|
2555
2660
|
i.onload = () => {
|
|
2556
|
-
this.restoreSel(),
|
|
2557
|
-
"insertHTML",
|
|
2558
|
-
!1,
|
|
2559
|
-
`<img src="${i.result}" title="${t.name.replace(/"/g, "")}" alt="">`
|
|
2560
|
-
), this.onChange();
|
|
2661
|
+
this.restoreSel(), this.insertImageHTML(i.result, t.name.replace(/"/g, "")), this.onChange();
|
|
2561
2662
|
}, i.readAsDataURL(t);
|
|
2562
2663
|
}), this.on(this.vidInput, "change", () => {
|
|
2563
2664
|
var s;
|
|
@@ -2581,7 +2682,7 @@ const I = class I {
|
|
|
2581
2682
|
const t = (e = this.docInput.files) == null ? void 0 : e[0];
|
|
2582
2683
|
t && this.importWordFile(t).catch(() => alert(this.t("importfail")));
|
|
2583
2684
|
}), this.onDoc("mousedown", (t) => {
|
|
2584
|
-
this.ed.contains(t.target) || t.target === this.tblCorner || this.tblColBars.includes(t.target) || this.tblCtx && this.tblCtx.contains(t.target) || this.imgHandles.includes(t.target) || this.imgCtx && this.imgCtx.contains(t.target) || this.phCtx && this.phCtx.contains(t.target) || this.tplCtx && this.tplCtx.contains(t.target) || this.selCtx && this.selCtx.contains(t.target) || this.vphCtx && this.vphCtx.contains(t.target) || this.vidCtx && this.vidCtx.contains(t.target) || this.codeCtx && this.codeCtx.contains(t.target) || this.openPop && this.openPop.contains(t.target) || this.
|
|
2685
|
+
this.ed.contains(t.target) || t.target === this.tblCorner || this.tblColBars.includes(t.target) || this.tblCtx && this.tblCtx.contains(t.target) || this.imgHandles.includes(t.target) || this.imgCtx && this.imgCtx.contains(t.target) || this.phCtx && this.phCtx.contains(t.target) || this.tplCtx && this.tplCtx.contains(t.target) || this.selCtx && this.selCtx.contains(t.target) || this.vphCtx && this.vphCtx.contains(t.target) || this.vidCtx && this.vidCtx.contains(t.target) || this.codeCtx && this.codeCtx.contains(t.target) || this.openPop && this.openPop.contains(t.target) || this.subContains(t.target) || (this.clearTableHandles(), this.clearImageHandles(), this.clearImgPlaceholderSel(), this.clearTplSel(), this.clearVphPlaceholderSel(), this.clearVidHandles(), this.clearCodeSel(), this.clearSelToolbar());
|
|
2585
2686
|
});
|
|
2586
2687
|
}
|
|
2587
2688
|
on(t, e, i) {
|
|
@@ -2611,33 +2712,41 @@ const I = class I {
|
|
|
2611
2712
|
* content with no strongly-directional character anywhere falls back to the
|
|
2612
2713
|
* editor's current direction. */
|
|
2613
2714
|
getContentForEmail() {
|
|
2614
|
-
const t = (o,
|
|
2615
|
-
const
|
|
2616
|
-
o.setAttribute("style",
|
|
2715
|
+
const t = (o, r) => {
|
|
2716
|
+
const a = (o.getAttribute("style") || "").trim();
|
|
2717
|
+
o.setAttribute("style", a ? a.replace(/;?$/, "; ") + r : r);
|
|
2617
2718
|
}, e = document.createElement("div");
|
|
2618
2719
|
e.innerHTML = this.ed.innerHTML;
|
|
2619
2720
|
let i = null;
|
|
2620
2721
|
e.querySelectorAll("[dir]").forEach((o) => {
|
|
2621
|
-
const
|
|
2622
|
-
if (
|
|
2623
|
-
const
|
|
2624
|
-
i || (i =
|
|
2625
|
-
}), e.querySelectorAll(
|
|
2626
|
-
const
|
|
2627
|
-
if (
|
|
2628
|
-
const
|
|
2629
|
-
if (!
|
|
2630
|
-
i || (i =
|
|
2631
|
-
const
|
|
2632
|
-
t(o,
|
|
2722
|
+
const r = (o.getAttribute("dir") || "").toLowerCase();
|
|
2723
|
+
if (r !== "rtl" && r !== "ltr") return;
|
|
2724
|
+
const a = r;
|
|
2725
|
+
i || (i = a), /text-align\s*:/i.test(o.getAttribute("style") || "") || t(o, `text-align:${a === "rtl" ? "right" : "left"}`);
|
|
2726
|
+
}), e.querySelectorAll(Yt).forEach((o) => {
|
|
2727
|
+
const r = (o.getAttribute("dir") || "").toLowerCase();
|
|
2728
|
+
if (r === "rtl" || r === "ltr") return;
|
|
2729
|
+
const a = Kt(ot(o));
|
|
2730
|
+
if (!a) return;
|
|
2731
|
+
i || (i = a), o.setAttribute("dir", a);
|
|
2732
|
+
const h = /text-align\s*:/i.test(o.getAttribute("style") || "");
|
|
2733
|
+
t(o, h ? `direction:${a}` : `direction:${a};text-align:${a === "rtl" ? "right" : "left"}`);
|
|
2633
2734
|
});
|
|
2634
|
-
const s =
|
|
2735
|
+
const s = this.ed.querySelectorAll("img");
|
|
2736
|
+
e.querySelectorAll("img").forEach((o, r) => {
|
|
2737
|
+
if (o.closest(".tpl-media")) return;
|
|
2738
|
+
const a = s[r], h = Math.round((a == null ? void 0 : a.getBoundingClientRect().width) || 0);
|
|
2739
|
+
h > 0 && !o.getAttribute("width") && o.setAttribute("width", String(h));
|
|
2740
|
+
const p = o.getAttribute("style") || "";
|
|
2741
|
+
h > 0 && !/(^|;)\s*width\s*:/i.test(p) && t(o, `width:${h}px`), /max-width\s*:/i.test(o.getAttribute("style") || "") || t(o, "max-width:100%"), /(^|;)\s*height\s*:/i.test(o.getAttribute("style") || "") || t(o, "height:auto");
|
|
2742
|
+
});
|
|
2743
|
+
const l = i || this.ed.getAttribute("dir") || this.dir();
|
|
2635
2744
|
return e.querySelectorAll("table:not([dir])").forEach((o) => {
|
|
2636
|
-
o.setAttribute("dir",
|
|
2637
|
-
}), `<div dir="${
|
|
2745
|
+
o.setAttribute("dir", l), /direction\s*:/i.test(o.getAttribute("style") || "") || t(o, `direction:${l}`);
|
|
2746
|
+
}), `<div dir="${l}" style="direction:${l};text-align:${l === "rtl" ? "right" : "left"}">${e.innerHTML}</div>`;
|
|
2638
2747
|
}
|
|
2639
2748
|
setContent(t) {
|
|
2640
|
-
this.ed.innerHTML = t || "<p><br></p>", this.refreshState(), this.clearTableHandles(), this.clearImageHandles(), this.clearImgPlaceholderSel(), this.clearTplSel(), this.clearVphPlaceholderSel(), this.clearVidHandles(), this.clearCodeSel(), this.clearSelToolbar(), this.onChange();
|
|
2749
|
+
this.ed.innerHTML = t || "<p><br></p>", this.refreshState(), this.clearTableHandles(), this.clearImageHandles(), this.clearImgPlaceholderSel(), this.clearTplSel(), this.clearVphPlaceholderSel(), this.clearVidHandles(), this.clearCodeSel(), this.clearSelToolbar(), this.onChange(), this.stampExistingImages();
|
|
2641
2750
|
}
|
|
2642
2751
|
insertContent(t) {
|
|
2643
2752
|
this.restoreSel(), document.execCommand("insertHTML", !1, t), this.saveSel(), this.refreshState(), this.onChange();
|
|
@@ -2649,7 +2758,7 @@ const I = class I {
|
|
|
2649
2758
|
this.ed.focus();
|
|
2650
2759
|
}
|
|
2651
2760
|
async importWordFile(t) {
|
|
2652
|
-
const e = await
|
|
2761
|
+
const e = await zt(t);
|
|
2653
2762
|
this.recordRevision(), this.setContent(e), this.recordRevision();
|
|
2654
2763
|
}
|
|
2655
2764
|
restoreDraft() {
|
|
@@ -2708,8 +2817,8 @@ const I = class I {
|
|
|
2708
2817
|
t.preventDefault();
|
|
2709
2818
|
const l = document.createElement("p");
|
|
2710
2819
|
l.appendChild(document.createElement("br")), s.after(l), i.remove(), s.firstElementChild || s.remove();
|
|
2711
|
-
const
|
|
2712
|
-
|
|
2820
|
+
const n = document.createRange();
|
|
2821
|
+
n.setStart(l, 0), n.collapse(!0), e.removeAllRanges(), e.addRange(n), this.saveSel(), this.onChange();
|
|
2713
2822
|
}
|
|
2714
2823
|
selectedBlocks() {
|
|
2715
2824
|
const t = window.getSelection();
|
|
@@ -2759,52 +2868,70 @@ const I = class I {
|
|
|
2759
2868
|
s.className = "revprev";
|
|
2760
2869
|
const l = document.createElement("button");
|
|
2761
2870
|
l.type = "button", l.className = "revrestore", l.textContent = this.t("restore");
|
|
2762
|
-
let
|
|
2763
|
-
const
|
|
2871
|
+
let n = this.revisions.length - 1;
|
|
2872
|
+
const o = new Intl.DateTimeFormat(this.lang === "ar" ? "ar-AE" : "en-GB", {
|
|
2764
2873
|
year: "numeric",
|
|
2765
2874
|
month: "short",
|
|
2766
2875
|
day: "numeric",
|
|
2767
2876
|
hour: "2-digit",
|
|
2768
2877
|
minute: "2-digit",
|
|
2769
2878
|
second: "2-digit"
|
|
2770
|
-
}), r = {},
|
|
2771
|
-
|
|
2879
|
+
}), r = {}, a = (h) => {
|
|
2880
|
+
n = h, this.revisions.forEach((p, m) => {
|
|
2772
2881
|
var g;
|
|
2773
2882
|
return (g = r[m]) == null ? void 0 : g.classList.toggle("on", m === h);
|
|
2774
2883
|
}), s.innerHTML = this.revisions[h].html, l.disabled = h === this.revisions.length - 1;
|
|
2775
2884
|
};
|
|
2776
2885
|
for (let h = this.revisions.length - 1; h >= 0; h--) {
|
|
2777
|
-
const
|
|
2886
|
+
const p = this.revisions[h], m = document.createElement("button");
|
|
2778
2887
|
m.type = "button";
|
|
2779
|
-
const g = (new DOMParser().parseFromString(
|
|
2780
|
-
m.innerHTML = `<span>${v ? this.t("currentver") :
|
|
2888
|
+
const g = (new DOMParser().parseFromString(p.html, "text/html").body.textContent || "").trim(), u = g ? g.split(/\s+/).length : 0, v = h === this.revisions.length - 1;
|
|
2889
|
+
m.innerHTML = `<span>${v ? this.t("currentver") : o.format(new Date(p.time))}</span><span class="wc">${u} ${this.t("words")}</span>`, m.addEventListener("click", () => a(h)), r[h] = m, i.appendChild(m);
|
|
2781
2890
|
}
|
|
2782
2891
|
i.append(l), l.addEventListener("click", () => {
|
|
2783
|
-
const h = this.revisions[
|
|
2892
|
+
const h = this.revisions[n];
|
|
2784
2893
|
h && (this.recordRevision(), this.setContent(h.html), this.recordRevision(), this.closeDlg());
|
|
2785
|
-
}), e.append(i, s), t.appendChild(e),
|
|
2894
|
+
}), e.append(i, s), t.appendChild(e), a(n);
|
|
2786
2895
|
});
|
|
2787
2896
|
}
|
|
2788
2897
|
/* ---------------------------------------------------------- popups / menus */
|
|
2789
2898
|
closeSub() {
|
|
2790
|
-
|
|
2791
|
-
|
|
2899
|
+
this.closeSubFrom(0);
|
|
2900
|
+
}
|
|
2901
|
+
/** Removes stacked flyouts from `level` (0 = shallowest) onward, keeping
|
|
2902
|
+
* anything shallower - e.g. hovering a sibling item inside the "Cell"
|
|
2903
|
+
* flyout should drop a deeper "Cell background" flyout but keep "Cell"
|
|
2904
|
+
* itself and the top-level popup it bridges to. */
|
|
2905
|
+
closeSubFrom(t) {
|
|
2906
|
+
for (; this.subStack.length > t; ) this.subStack.pop().remove();
|
|
2907
|
+
}
|
|
2908
|
+
/** True if `node` is inside any currently-open flyout submenu (any depth). */
|
|
2909
|
+
subContains(t) {
|
|
2910
|
+
return this.subStack.some((e) => e.contains(t));
|
|
2911
|
+
}
|
|
2912
|
+
/** 0 for the top-level popup itself; otherwise this container's depth in
|
|
2913
|
+
* the flyout stack + 1. Used to know how many deeper flyouts to close
|
|
2914
|
+
* when opening or hovering within `container`. */
|
|
2915
|
+
subLevelOf(t) {
|
|
2916
|
+
if (t === this.openPop) return 0;
|
|
2917
|
+
const e = this.subStack.indexOf(t);
|
|
2918
|
+
return e === -1 ? this.subStack.length : e + 1;
|
|
2792
2919
|
}
|
|
2793
2920
|
closePop() {
|
|
2794
2921
|
var t;
|
|
2795
2922
|
this.closeSub(), this.openPop && (this.openPop.remove(), this.openPop = null, (t = this.popAnchor) == null || t.classList.remove("open"), this.popAnchor = null, this.setOpTarget(null));
|
|
2796
2923
|
}
|
|
2797
2924
|
openSubFor(t, e) {
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
let o = this.dir() === "rtl" ?
|
|
2805
|
-
o = Math.max(8, Math.min(o + scrollX, scrollX + innerWidth -
|
|
2806
|
-
let
|
|
2807
|
-
|
|
2925
|
+
const i = e.getBoundingClientRect(), s = e.closest(".pop");
|
|
2926
|
+
this.closeSubFrom(s ? this.subLevelOf(s) : 0);
|
|
2927
|
+
const l = document.createElement("div");
|
|
2928
|
+
l.className = "pop sub", l.dir = this.dir(), t.subBuild ? t.subBuild(l) : t.sub && this.menuItems(l, t.sub), l.addEventListener("mousedown", (a) => {
|
|
2929
|
+
a.target.tagName !== "INPUT" && a.preventDefault();
|
|
2930
|
+
}), document.body.appendChild(l);
|
|
2931
|
+
let o = this.dir() === "rtl" ? i.left - l.offsetWidth + 2 : i.right - 2;
|
|
2932
|
+
o = Math.max(8, Math.min(o + scrollX, scrollX + innerWidth - l.offsetWidth - 8));
|
|
2933
|
+
let r = i.top + scrollY - 6;
|
|
2934
|
+
r = Math.max(8 + scrollY, Math.min(r, scrollY + innerHeight - l.offsetHeight - 8)), l.style.left = o + "px", l.style.top = r + "px", this.subStack.push(l);
|
|
2808
2935
|
}
|
|
2809
2936
|
popup(t, e, i) {
|
|
2810
2937
|
if (this.openPop && this.popAnchor === t) {
|
|
@@ -2815,10 +2942,12 @@ const I = class I {
|
|
|
2815
2942
|
const s = document.createElement("div");
|
|
2816
2943
|
s.className = "pop" + (i ? " " + i : ""), s.dir = this.dir(), e(s), document.body.appendChild(s);
|
|
2817
2944
|
const l = t.getBoundingClientRect();
|
|
2818
|
-
s.style.minWidth = Math.max(160, Math.round(l.width)) + "px"
|
|
2819
|
-
let n =
|
|
2820
|
-
n = Math.max(8, Math.min(n
|
|
2821
|
-
|
|
2945
|
+
s.style.minWidth = Math.max(160, Math.round(l.width)) + "px";
|
|
2946
|
+
let n = l.bottom + scrollY + 2;
|
|
2947
|
+
n = Math.max(8 + scrollY, Math.min(n, scrollY + innerHeight - s.offsetHeight - 8)), s.style.top = n + "px";
|
|
2948
|
+
let r = this.dir() === "rtl" ? l.right - s.offsetWidth : l.left;
|
|
2949
|
+
r = Math.max(8, Math.min(r + scrollX, scrollX + innerWidth - s.offsetWidth - 8)), s.style.left = r + "px", s.addEventListener("mousedown", (a) => {
|
|
2950
|
+
a.target.tagName !== "INPUT" && a.preventDefault();
|
|
2822
2951
|
}), this.openPop = s, this.popAnchor = t, t.classList.add("open");
|
|
2823
2952
|
}
|
|
2824
2953
|
menuItems(t, e) {
|
|
@@ -2828,44 +2957,44 @@ const I = class I {
|
|
|
2828
2957
|
return;
|
|
2829
2958
|
}
|
|
2830
2959
|
const s = !!(i.sub || i.subBuild), l = document.createElement("button");
|
|
2831
|
-
l.className = "mi" + (i.on ? " on" : ""), l.innerHTML = `<span class="ic">${i.icon || ""}</span><span class="prev" ${i.previewStyle ? `style="${i.previewStyle}"` : ""}>${i.label}</span>${i.shortcut ? `<span class="sc">${i.shortcut}</span>` : ""}${s ? `<span class="subarrow">${
|
|
2960
|
+
l.className = "mi" + (i.on ? " on" : ""), l.innerHTML = `<span class="ic">${i.icon || ""}</span><span class="prev" ${i.previewStyle ? `style="${i.previewStyle}"` : ""}>${i.label}</span>${i.shortcut ? `<span class="sc">${i.shortcut}</span>` : ""}${s ? `<span class="subarrow">${c.chev}</span>` : ""}`, l.addEventListener("click", () => {
|
|
2832
2961
|
i.action && (this.closePop(), i.action());
|
|
2833
2962
|
}), l.addEventListener("mouseenter", () => {
|
|
2834
|
-
var
|
|
2835
|
-
s ? this.openSubFor(i, l) : this.
|
|
2963
|
+
var n;
|
|
2964
|
+
s ? this.openSubFor(i, l) : this.closeSubFrom(this.subLevelOf(t)), (n = i.hover) == null || n.call(i, !0);
|
|
2836
2965
|
}), l.addEventListener("mouseleave", () => {
|
|
2837
|
-
var
|
|
2838
|
-
return (
|
|
2966
|
+
var n;
|
|
2967
|
+
return (n = i.hover) == null ? void 0 : n.call(i, !1);
|
|
2839
2968
|
}), t.appendChild(l);
|
|
2840
2969
|
});
|
|
2841
2970
|
}
|
|
2842
2971
|
/* ---------------------------------------------------------- toolbar builders */
|
|
2843
2972
|
tbtn(t, e, i, s) {
|
|
2844
2973
|
const l = document.createElement("button");
|
|
2845
|
-
return l.className = "tbtn", l.type = "button", l.title = e, l.innerHTML = t, s && (l.dataset.id = s), l.addEventListener("mousedown", (
|
|
2974
|
+
return l.className = "tbtn", l.type = "button", l.title = e, l.innerHTML = t, s && (l.dataset.id = s), l.addEventListener("mousedown", (n) => n.preventDefault()), l.addEventListener("click", i), l;
|
|
2846
2975
|
}
|
|
2847
2976
|
/** Font-size increase / decrease step button. */
|
|
2848
2977
|
stepBtn(t) {
|
|
2849
|
-
const e = t > 0 ? "+" : "−", i = t > 0 ?
|
|
2978
|
+
const e = t > 0 ? "+" : "−", i = t > 0 ? c.fontsizeup : c.fontsizedown, s = this.tbtn(i, this.t("fontsize") + " " + e, () => this.stepFontSize(t));
|
|
2850
2979
|
return s.addEventListener("mousedown", () => this.saveSel()), s;
|
|
2851
2980
|
}
|
|
2852
2981
|
/** Toolbar icon button that opens a popup menu anchored to itself. */
|
|
2853
2982
|
menuTbtn(t, e, i, s) {
|
|
2854
2983
|
const l = this.tbtn(t, e, () => i(l), s);
|
|
2855
|
-
return l.classList.add("hasmenu"), l.insertAdjacentHTML("beforeend",
|
|
2984
|
+
return l.classList.add("hasmenu"), l.insertAdjacentHTML("beforeend", c.chev), l.addEventListener("mousedown", () => this.saveSel()), l;
|
|
2856
2985
|
}
|
|
2857
2986
|
/** Quick text-color chips plus a "more" chip that opens the full palette. */
|
|
2858
2987
|
colorChips() {
|
|
2859
2988
|
const t = (s) => {
|
|
2860
2989
|
const l = document.createElement("button");
|
|
2861
|
-
return l.type = "button", l.className = "cchip", l.title = s, l.addEventListener("mousedown", (
|
|
2862
|
-
|
|
2990
|
+
return l.type = "button", l.className = "cchip", l.title = s, l.addEventListener("mousedown", (n) => {
|
|
2991
|
+
n.preventDefault(), this.saveSel();
|
|
2863
2992
|
}), l;
|
|
2864
|
-
}, e =
|
|
2993
|
+
}, e = ut.map((s) => {
|
|
2865
2994
|
const l = t(this.t("forecolor"));
|
|
2866
2995
|
return l.style.background = s, l.addEventListener("click", () => this.applyColor("fore", s)), l;
|
|
2867
2996
|
}), i = t(this.t("forecolor"));
|
|
2868
|
-
return i.classList.add("more"), i.dataset.cb = "fore", i.innerHTML =
|
|
2997
|
+
return i.classList.add("more"), i.dataset.cb = "fore", i.innerHTML = c.chev, i.addEventListener("click", () => this.colorMenu(i, "fore")), [...e, i];
|
|
2869
2998
|
}
|
|
2870
2999
|
group(...t) {
|
|
2871
3000
|
const e = document.createElement("div");
|
|
@@ -2875,45 +3004,45 @@ const I = class I {
|
|
|
2875
3004
|
}
|
|
2876
3005
|
tsel(t, e, i, s) {
|
|
2877
3006
|
const l = document.createElement("button");
|
|
2878
|
-
return l.className = "tsel " + t, l.type = "button", l.dataset.id = e, l.innerHTML = `<span class="lbl empty">${i || ""}</span>${
|
|
2879
|
-
|
|
3007
|
+
return l.className = "tsel " + t, l.type = "button", l.dataset.id = e, l.innerHTML = `<span class="lbl empty">${i || ""}</span>${c.chev}`, l.addEventListener("mousedown", (n) => {
|
|
3008
|
+
n.preventDefault(), this.saveSel();
|
|
2880
3009
|
}), l.addEventListener("click", () => s(l)), l;
|
|
2881
3010
|
}
|
|
2882
3011
|
setListStyle(t, e) {
|
|
2883
|
-
var l,
|
|
3012
|
+
var l, n;
|
|
2884
3013
|
this.restoreSel();
|
|
2885
3014
|
const i = window.getSelection();
|
|
2886
3015
|
if (!i) return;
|
|
2887
3016
|
let s = (l = this.closestBlock(i.anchorNode)) == null ? void 0 : l.closest(t);
|
|
2888
|
-
s || (this.exec(t === "ol" ? "insertOrderedList" : "insertUnorderedList"), s = (
|
|
3017
|
+
s || (this.exec(t === "ol" ? "insertOrderedList" : "insertUnorderedList"), s = (n = this.closestBlock(i.anchorNode)) == null ? void 0 : n.closest(t)), s && (s.style.listStyleType = e), this.saveSel(), this.onChange();
|
|
2889
3018
|
}
|
|
2890
3019
|
listMenu(t, e) {
|
|
2891
|
-
var
|
|
3020
|
+
var a;
|
|
2892
3021
|
const i = e === "ol" ? "insertOrderedList" : "insertUnorderedList", s = e === "ol" ? [
|
|
2893
|
-
["lower-alpha",
|
|
2894
|
-
["lower-roman",
|
|
2895
|
-
["upper-alpha",
|
|
2896
|
-
["upper-roman",
|
|
3022
|
+
["lower-alpha", c.ol_alpha],
|
|
3023
|
+
["lower-roman", c.ol_roman],
|
|
3024
|
+
["upper-alpha", c.ol_alphau],
|
|
3025
|
+
["upper-roman", c.ol_romanu]
|
|
2897
3026
|
] : [
|
|
2898
|
-
["circle",
|
|
2899
|
-
["square",
|
|
2900
|
-
], l = this.tArr(e === "ol" ? "liststyles_ol" : "liststyles_ul").slice(1),
|
|
3027
|
+
["circle", c.ul_circle],
|
|
3028
|
+
["square", c.ul_square]
|
|
3029
|
+
], l = this.tArr(e === "ol" ? "liststyles_ol" : "liststyles_ul").slice(1), n = window.getSelection(), o = n ? (a = this.closestBlock(n.anchorNode)) == null ? void 0 : a.closest(e) : null, r = o ? o.style.listStyleType : "";
|
|
2901
3030
|
this.popup(t, (h) => {
|
|
2902
3031
|
this.menuItems(h, [
|
|
2903
3032
|
{
|
|
2904
3033
|
label: this.t(e === "ol" ? "numlist" : "bullist"),
|
|
2905
|
-
icon: e === "ol" ?
|
|
3034
|
+
icon: e === "ol" ? c.numlist : c.bullist,
|
|
2906
3035
|
on: document.queryCommandState(i),
|
|
2907
3036
|
action: () => this.exec(i)
|
|
2908
3037
|
}
|
|
2909
3038
|
]), h.insertAdjacentHTML("beforeend", '<div class="sep"></div>');
|
|
2910
|
-
const
|
|
2911
|
-
|
|
3039
|
+
const p = document.createElement("div");
|
|
3040
|
+
p.className = "mi-grid", s.forEach(([m, g], u) => {
|
|
2912
3041
|
const v = document.createElement("button");
|
|
2913
3042
|
v.className = "mi" + (r === m ? " on" : ""), v.innerHTML = `<span class="ic">${g}</span><span class="prev">${l[u]}</span>`, v.addEventListener("click", () => {
|
|
2914
3043
|
this.closePop(), this.setListStyle(e, m);
|
|
2915
|
-
}),
|
|
2916
|
-
}), h.appendChild(
|
|
3044
|
+
}), p.appendChild(v);
|
|
3045
|
+
}), h.appendChild(p);
|
|
2917
3046
|
});
|
|
2918
3047
|
}
|
|
2919
3048
|
/** Shared color-picker popup body — swatch grid plus the current-color /
|
|
@@ -2921,26 +3050,26 @@ const I = class I {
|
|
|
2921
3050
|
* table cell-background menu all show the identical popup. */
|
|
2922
3051
|
buildPaletteInto(t, e, i) {
|
|
2923
3052
|
const s = document.createElement("div");
|
|
2924
|
-
s.className = "cpal",
|
|
3053
|
+
s.className = "cpal", gt.forEach((p) => {
|
|
2925
3054
|
const m = document.createElement("button");
|
|
2926
|
-
m.type = "button", m.style.background =
|
|
2927
|
-
this.closePop(), i(
|
|
3055
|
+
m.type = "button", m.style.background = p, m.title = p, m.addEventListener("click", () => {
|
|
3056
|
+
this.closePop(), i(p);
|
|
2928
3057
|
}), s.appendChild(m);
|
|
2929
3058
|
}), t.appendChild(s), t.insertAdjacentHTML("beforeend", '<div class="sep"></div>');
|
|
2930
3059
|
const l = document.createElement("div");
|
|
2931
3060
|
l.className = "cfoot";
|
|
2932
|
-
const
|
|
2933
|
-
|
|
3061
|
+
const n = /^#[0-9a-f]{6}$/i.test(e) ? e : "#000000", o = document.createElement("div");
|
|
3062
|
+
o.className = "cswatch cur", o.title = this.t("currentcolor"), o.style.background = n, o.innerHTML = c.check;
|
|
2934
3063
|
const r = document.createElement("button");
|
|
2935
3064
|
r.type = "button", r.className = "cswatch nocolor", r.title = this.t("removecolor"), r.addEventListener("click", () => {
|
|
2936
3065
|
this.closePop(), i(null);
|
|
2937
3066
|
});
|
|
2938
|
-
const
|
|
2939
|
-
|
|
3067
|
+
const a = document.createElement("label");
|
|
3068
|
+
a.className = "cswatch cwheel", a.title = this.t("customcolor"), a.innerHTML = c.palette;
|
|
2940
3069
|
const h = document.createElement("input");
|
|
2941
|
-
h.type = "color", h.value =
|
|
3070
|
+
h.type = "color", h.value = n, h.addEventListener("change", () => {
|
|
2942
3071
|
this.closePop(), i(h.value);
|
|
2943
|
-
}),
|
|
3072
|
+
}), a.appendChild(h), l.append(o, r, a), t.appendChild(l);
|
|
2944
3073
|
}
|
|
2945
3074
|
colorMenu(t, e) {
|
|
2946
3075
|
this.popup(
|
|
@@ -2970,7 +3099,7 @@ const I = class I {
|
|
|
2970
3099
|
this.popup(t, (e) => this.menuItems(e, this.fontItems()));
|
|
2971
3100
|
}
|
|
2972
3101
|
sizeItems() {
|
|
2973
|
-
return
|
|
3102
|
+
return dt.map((t) => ({
|
|
2974
3103
|
label: t,
|
|
2975
3104
|
on: this.currentSize() === t,
|
|
2976
3105
|
action: () => this.applyFontSize(t)
|
|
@@ -2986,19 +3115,19 @@ const I = class I {
|
|
|
2986
3115
|
const t = window.getSelection();
|
|
2987
3116
|
if (!t) return;
|
|
2988
3117
|
if (!t.rangeCount) {
|
|
2989
|
-
const
|
|
2990
|
-
|
|
3118
|
+
const n = document.createRange();
|
|
3119
|
+
n.selectNodeContents(this.ed), n.collapse(!0), t.addRange(n);
|
|
2991
3120
|
}
|
|
2992
3121
|
if (!t.isCollapsed) return;
|
|
2993
3122
|
const e = t.getRangeAt(0), i = e.startContainer;
|
|
2994
3123
|
if (i.nodeType === 3) {
|
|
2995
|
-
const
|
|
2996
|
-
let
|
|
2997
|
-
for (;
|
|
2998
|
-
for (; r <
|
|
2999
|
-
if (r >
|
|
3000
|
-
const
|
|
3001
|
-
|
|
3124
|
+
const n = i.data;
|
|
3125
|
+
let o = e.startOffset, r = e.startOffset;
|
|
3126
|
+
for (; o > 0 && /\S/.test(n[o - 1]); ) o--;
|
|
3127
|
+
for (; r < n.length && /\S/.test(n[r]); ) r++;
|
|
3128
|
+
if (r > o) {
|
|
3129
|
+
const a = document.createRange();
|
|
3130
|
+
a.setStart(i, o), a.setEnd(i, r), t.removeAllRanges(), t.addRange(a), this.savedRange = a.cloneRange();
|
|
3002
3131
|
return;
|
|
3003
3132
|
}
|
|
3004
3133
|
}
|
|
@@ -3023,7 +3152,7 @@ const I = class I {
|
|
|
3023
3152
|
this.saveSel(), this.refreshState(), this.onChange();
|
|
3024
3153
|
}
|
|
3025
3154
|
stepFontSize(t) {
|
|
3026
|
-
const e = parseInt(this.currentSize(), 10) || 14, i = Math.min(
|
|
3155
|
+
const e = parseInt(this.currentSize(), 10) || 14, i = Math.min(mt, Math.max(pt, e + t));
|
|
3027
3156
|
i !== e && this.applyFontSize(i + "px");
|
|
3028
3157
|
}
|
|
3029
3158
|
/* ------------------------------------------------ case / spacing / link */
|
|
@@ -3032,21 +3161,21 @@ const I = class I {
|
|
|
3032
3161
|
const e = window.getSelection();
|
|
3033
3162
|
if (!e || !e.rangeCount || e.isCollapsed) return;
|
|
3034
3163
|
const i = e.getRangeAt(0), s = document.createTreeWalker(this.ed, NodeFilter.SHOW_TEXT), l = [];
|
|
3035
|
-
let
|
|
3036
|
-
for (;
|
|
3037
|
-
l.forEach((
|
|
3038
|
-
const r =
|
|
3039
|
-
if (
|
|
3040
|
-
const h =
|
|
3041
|
-
let
|
|
3042
|
-
t === "lower" ?
|
|
3164
|
+
let n;
|
|
3165
|
+
for (; n = s.nextNode(); ) i.intersectsNode(n) && l.push(n);
|
|
3166
|
+
l.forEach((o) => {
|
|
3167
|
+
const r = o === i.startContainer ? i.startOffset : 0, a = o === i.endContainer ? i.endOffset : o.data.length;
|
|
3168
|
+
if (a <= r) return;
|
|
3169
|
+
const h = o.data.slice(r, a);
|
|
3170
|
+
let p = h;
|
|
3171
|
+
t === "lower" ? p = h.toLowerCase() : t === "upper" ? p = h.toUpperCase() : p = h.replace(/(^|\s)(\S)/g, (m, g, u) => g + u.toUpperCase()), o.replaceData(r, a - r, p);
|
|
3043
3172
|
}), this.saveSel(), this.refreshState(), this.onChange();
|
|
3044
3173
|
}
|
|
3045
3174
|
caseItems() {
|
|
3046
3175
|
return [
|
|
3047
|
-
{ label: this.t("lowercase"), icon:
|
|
3048
|
-
{ label: this.t("uppercase"), icon:
|
|
3049
|
-
{ label: this.t("capitalize"), icon:
|
|
3176
|
+
{ label: this.t("lowercase"), icon: c.lowercaseic, action: () => this.transformCase("lower") },
|
|
3177
|
+
{ label: this.t("uppercase"), icon: c.uppercaseic, action: () => this.transformCase("upper") },
|
|
3178
|
+
{ label: this.t("capitalize"), icon: c.capitalizeic, action: () => this.transformCase("capitalize") }
|
|
3050
3179
|
];
|
|
3051
3180
|
}
|
|
3052
3181
|
caseMenu(t) {
|
|
@@ -3075,13 +3204,13 @@ const I = class I {
|
|
|
3075
3204
|
];
|
|
3076
3205
|
}
|
|
3077
3206
|
lineHeightMenu(t) {
|
|
3078
|
-
this.popup(t, (e) => this.menuItems(e, this.blockStyleItems("lineHeight",
|
|
3207
|
+
this.popup(t, (e) => this.menuItems(e, this.blockStyleItems("lineHeight", U)));
|
|
3079
3208
|
}
|
|
3080
3209
|
wordSpacingMenu(t) {
|
|
3081
|
-
this.popup(t, (e) => this.menuItems(e, this.blockStyleItems("wordSpacing",
|
|
3210
|
+
this.popup(t, (e) => this.menuItems(e, this.blockStyleItems("wordSpacing", W)));
|
|
3082
3211
|
}
|
|
3083
3212
|
letterSpacingMenu(t) {
|
|
3084
|
-
this.popup(t, (e) => this.menuItems(e, this.blockStyleItems("letterSpacing",
|
|
3213
|
+
this.popup(t, (e) => this.menuItems(e, this.blockStyleItems("letterSpacing", j)));
|
|
3085
3214
|
}
|
|
3086
3215
|
closestAnchor() {
|
|
3087
3216
|
const t = window.getSelection();
|
|
@@ -3127,14 +3256,14 @@ const I = class I {
|
|
|
3127
3256
|
(s) => {
|
|
3128
3257
|
const l = document.createElement("div");
|
|
3129
3258
|
l.style.cssText = "display:flex;align-items:center;gap:10px;margin:10px 0;min-width:360px";
|
|
3130
|
-
const
|
|
3131
|
-
|
|
3259
|
+
const n = document.createElement("span");
|
|
3260
|
+
n.style.cssText = "width:60px;color:#556;flex:none", n.textContent = this.t("linkurl"), e = document.createElement("input"), e.type = "url", e.placeholder = "https://", e.style.cssText = "flex:1;border:1px solid #cfd6df;border-radius:6px;padding:7px 9px;font:14px inherit", e.value = (t == null ? void 0 : t.getAttribute("href")) || "", l.append(n, e), s.appendChild(l), setTimeout(() => e.focus(), 0);
|
|
3132
3261
|
},
|
|
3133
3262
|
i
|
|
3134
3263
|
);
|
|
3135
3264
|
}
|
|
3136
3265
|
blockItems() {
|
|
3137
|
-
return
|
|
3266
|
+
return X.map(([t]) => ({
|
|
3138
3267
|
label: this.blockLabel(t),
|
|
3139
3268
|
previewStyle: t.startsWith("h") ? `font-weight:700;font-size:${22 - 2 * +t[1]}px` : t === "pre" ? "font-family:monospace" : "",
|
|
3140
3269
|
on: this.currentBlock() === t,
|
|
@@ -3146,10 +3275,10 @@ const I = class I {
|
|
|
3146
3275
|
}
|
|
3147
3276
|
alignItems() {
|
|
3148
3277
|
return [
|
|
3149
|
-
["justifyLeft", "alignleft",
|
|
3150
|
-
["justifyCenter", "aligncenter",
|
|
3151
|
-
["justifyRight", "alignright",
|
|
3152
|
-
["justifyFull", "alignjustify",
|
|
3278
|
+
["justifyLeft", "alignleft", c.alignleft],
|
|
3279
|
+
["justifyCenter", "aligncenter", c.aligncenter],
|
|
3280
|
+
["justifyRight", "alignright", c.alignright],
|
|
3281
|
+
["justifyFull", "alignjustify", c.alignjustify]
|
|
3153
3282
|
].map(([e, i, s]) => ({
|
|
3154
3283
|
label: this.t(i),
|
|
3155
3284
|
icon: s,
|
|
@@ -3171,15 +3300,15 @@ const I = class I {
|
|
|
3171
3300
|
s.className = "tgrid";
|
|
3172
3301
|
const l = document.createElement("div");
|
|
3173
3302
|
l.className = "tgridlbl", l.textContent = "1 × 1";
|
|
3174
|
-
const
|
|
3175
|
-
for (let
|
|
3303
|
+
const n = [];
|
|
3304
|
+
for (let o = 0; o < 8; o++)
|
|
3176
3305
|
for (let r = 0; r < 10; r++) {
|
|
3177
|
-
const
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
}),
|
|
3181
|
-
this.closePop(), this.insertTable(
|
|
3182
|
-
}),
|
|
3306
|
+
const a = document.createElement("span");
|
|
3307
|
+
a.dataset.r = String(o), a.dataset.c = String(r), a.addEventListener("mouseenter", () => {
|
|
3308
|
+
n.forEach((h) => h.classList.toggle("hot", +h.dataset.r <= o && +h.dataset.c <= r)), l.textContent = r + 1 + " × " + (o + 1);
|
|
3309
|
+
}), a.addEventListener("click", () => {
|
|
3310
|
+
this.closePop(), this.insertTable(o + 1, r + 1), e == null || e();
|
|
3311
|
+
}), n.push(a), s.appendChild(a);
|
|
3183
3312
|
}
|
|
3184
3313
|
i.append(s, l), t.appendChild(i);
|
|
3185
3314
|
}
|
|
@@ -3210,73 +3339,73 @@ const I = class I {
|
|
|
3210
3339
|
* behavior changes, just named lookup. Only `forecolor` yields multiple elements
|
|
3211
3340
|
* (the quick color chips); everything else yields one. */
|
|
3212
3341
|
buildToolbarRegistry() {
|
|
3213
|
-
const t = this.tbtn(
|
|
3214
|
-
undo: () => this.tbtn(
|
|
3215
|
-
redo: () => this.tbtn(
|
|
3216
|
-
preview: () => this.tbtn(
|
|
3217
|
-
print: () => this.tbtn(
|
|
3218
|
-
importword: () => this.tbtn(
|
|
3219
|
-
revhistory: () => this.tbtn(
|
|
3342
|
+
const t = this.tbtn(c.tableic, this.t("quicktable"), () => this.tableGrid(t)), e = {
|
|
3343
|
+
undo: () => this.tbtn(c.undo, this.t("undo"), () => this.exec("undo"), "undo"),
|
|
3344
|
+
redo: () => this.tbtn(c.redo, this.t("redo"), () => this.exec("redo"), "redo"),
|
|
3345
|
+
preview: () => this.tbtn(c.prevw, this.t("preview"), () => this.previewDlg()),
|
|
3346
|
+
print: () => this.tbtn(c.printic, this.t("print"), () => this.printDoc()),
|
|
3347
|
+
importword: () => this.tbtn(c.wordic, this.t("importword"), () => this.pickWordDoc()),
|
|
3348
|
+
revhistory: () => this.tbtn(c.historyic, this.t("revhistory"), () => this.revisionDlg()),
|
|
3220
3349
|
fontfamily: () => this.tsel("w-font", "fontsel", "", (i) => this.fontMenu(i)),
|
|
3221
3350
|
fontsize: () => this.tsel("w-size", "sizesel", "", (i) => this.sizeMenu(i)),
|
|
3222
3351
|
fontsizeincrease: () => this.stepBtn(1),
|
|
3223
3352
|
fontsizedecrease: () => this.stepBtn(-1),
|
|
3224
|
-
bold: () => this.tbtn(
|
|
3225
|
-
italic: () => this.tbtn(
|
|
3226
|
-
underline: () => this.tbtn(
|
|
3227
|
-
strikethrough: () => this.tbtn(
|
|
3353
|
+
bold: () => this.tbtn(c.bold, this.t("bold"), () => this.exec("bold"), "bold"),
|
|
3354
|
+
italic: () => this.tbtn(c.italic, this.t("italic"), () => this.exec("italic"), "italic"),
|
|
3355
|
+
underline: () => this.tbtn(c.underline, this.t("underline"), () => this.exec("underline"), "underline"),
|
|
3356
|
+
strikethrough: () => this.tbtn(c.strikethrough, this.t("strikethrough"), () => this.exec("strikeThrough"), "strikeThrough"),
|
|
3228
3357
|
forecolor: () => this.colorChips(),
|
|
3229
3358
|
backcolor: () => this.menuTbtn(
|
|
3230
|
-
|
|
3359
|
+
c.backcolor + '<span class="colorbar" data-cb="back"></span>',
|
|
3231
3360
|
this.t("backcolor"),
|
|
3232
3361
|
(i) => this.colorMenu(i, "back")
|
|
3233
3362
|
),
|
|
3234
|
-
alignleft: () => this.tbtn(
|
|
3235
|
-
aligncenter: () => this.tbtn(
|
|
3236
|
-
alignright: () => this.tbtn(
|
|
3237
|
-
alignjustify: () => this.tbtn(
|
|
3238
|
-
bullist: () => this.menuTbtn(
|
|
3239
|
-
numlist: () => this.menuTbtn(
|
|
3240
|
-
outdent: () => this.tbtn(
|
|
3241
|
-
indent: () => this.tbtn(
|
|
3242
|
-
link: () => this.tbtn(
|
|
3243
|
-
blockquote: () => this.tbtn(
|
|
3244
|
-
code: () => this.tbtn(
|
|
3245
|
-
codesample: () => this.tbtn(
|
|
3246
|
-
changecase: () => this.menuTbtn(
|
|
3247
|
-
lineheight: () => this.menuTbtn(
|
|
3248
|
-
wordspacing: () => this.menuTbtn(
|
|
3249
|
-
letterspacing: () => this.menuTbtn(
|
|
3250
|
-
removeformat: () => this.tbtn(
|
|
3363
|
+
alignleft: () => this.tbtn(c.alignleft, this.t("alignleft"), () => this.exec("justifyLeft"), "justifyLeft"),
|
|
3364
|
+
aligncenter: () => this.tbtn(c.aligncenter, this.t("aligncenter"), () => this.exec("justifyCenter"), "justifyCenter"),
|
|
3365
|
+
alignright: () => this.tbtn(c.alignright, this.t("alignright"), () => this.exec("justifyRight"), "justifyRight"),
|
|
3366
|
+
alignjustify: () => this.tbtn(c.alignjustify, this.t("alignjustify"), () => this.exec("justifyFull"), "justifyFull"),
|
|
3367
|
+
bullist: () => this.menuTbtn(c.bullist, this.t("bullist"), (i) => this.listMenu(i, "ul"), "insertUnorderedList"),
|
|
3368
|
+
numlist: () => this.menuTbtn(c.numlist, this.t("numlist"), (i) => this.listMenu(i, "ol"), "insertOrderedList"),
|
|
3369
|
+
outdent: () => this.tbtn(c.outdent, this.t("outdent"), () => this.exec("outdent")),
|
|
3370
|
+
indent: () => this.tbtn(c.indent, this.t("indent"), () => this.exec("indent")),
|
|
3371
|
+
link: () => this.tbtn(c.link, this.t("linkttl"), () => this.linkDlg()),
|
|
3372
|
+
blockquote: () => this.tbtn(c.quote, this.t("quote"), () => this.toggleBlock("blockquote"), "blockquote"),
|
|
3373
|
+
code: () => this.tbtn(c.inlinecodeic, this.t("code"), () => this.toggleInlineCode(), "code"),
|
|
3374
|
+
codesample: () => this.tbtn(c.codesampleic, this.t("codesample"), () => this.codeDlg()),
|
|
3375
|
+
changecase: () => this.menuTbtn(c.caseic, this.t("changecase"), (i) => this.caseMenu(i)),
|
|
3376
|
+
lineheight: () => this.menuTbtn(c.lineheight, this.t("lineheight"), (i) => this.lineHeightMenu(i)),
|
|
3377
|
+
wordspacing: () => this.menuTbtn(c.wordspacing, this.t("wordspacing"), (i) => this.wordSpacingMenu(i)),
|
|
3378
|
+
letterspacing: () => this.menuTbtn(c.letterspacing, this.t("letterspacing"), (i) => this.letterSpacingMenu(i)),
|
|
3379
|
+
removeformat: () => this.tbtn(c.clearformatic, this.t("removeformat"), () => this.exec("removeFormat")),
|
|
3251
3380
|
blocks: () => this.tsel("w-block", "blocksel", this.t("para"), (i) => this.blocksMenu(i)),
|
|
3252
|
-
ltr: () => this.tbtn(
|
|
3253
|
-
rtl: () => this.tbtn(
|
|
3254
|
-
quickimage: () => this.tbtn(
|
|
3255
|
-
quickvideo: () => this.tbtn(
|
|
3381
|
+
ltr: () => this.tbtn(c.ltr, this.t("ltr"), () => this.setDir("ltr"), "ltr"),
|
|
3382
|
+
rtl: () => this.tbtn(c.rtl, this.t("rtl"), () => this.setDir("rtl"), "rtl"),
|
|
3383
|
+
quickimage: () => this.tbtn(c.image, this.t("quickimage"), () => this.insertImagePlaceholder()),
|
|
3384
|
+
quickvideo: () => this.tbtn(c.video, this.t("quickvideo"), () => this.videoDlg()),
|
|
3256
3385
|
quicktable: () => t,
|
|
3257
|
-
template: () => this.menuTbtn(
|
|
3258
|
-
charmap: () => this.tbtn(
|
|
3259
|
-
emoji: () => this.tbtn(
|
|
3260
|
-
fullscreen: () => this.tbtn(
|
|
3261
|
-
sourcecode: () => this.tbtn(
|
|
3386
|
+
template: () => this.menuTbtn(c.templateic, this.t("template"), (i) => this.templateMenu(i)),
|
|
3387
|
+
charmap: () => this.tbtn(c.charic, this.t("charmap"), () => this.charMap()),
|
|
3388
|
+
emoji: () => this.tbtn(c.emojiic, this.t("emoji"), () => this.emojiMap()),
|
|
3389
|
+
fullscreen: () => this.tbtn(c.fullscreen, this.t("fullscreen"), () => this.toggleFullscreen(), "fullscreen"),
|
|
3390
|
+
sourcecode: () => this.tbtn(c.srcic, this.t("sourcecode"), () => this.sourceDlg())
|
|
3262
3391
|
};
|
|
3263
3392
|
return e.styles = e.blocks, e.image = e.quickimage, e.media = e.quickvideo, e.table = e.quicktable, e;
|
|
3264
3393
|
}
|
|
3265
3394
|
buildToolbar() {
|
|
3266
3395
|
this.toolbar.innerHTML = "";
|
|
3267
|
-
const t = this.options.toolbar === !0 ?
|
|
3396
|
+
const t = this.options.toolbar === !0 ? at : this.options.toolbar, e = this.buildToolbarRegistry();
|
|
3268
3397
|
this.parseToolbarString(t).forEach((i) => {
|
|
3269
3398
|
const s = [];
|
|
3270
3399
|
i.forEach((l) => {
|
|
3271
|
-
const
|
|
3272
|
-
if (!
|
|
3400
|
+
const n = e[l];
|
|
3401
|
+
if (!n) {
|
|
3273
3402
|
console.warn(`FableEditor: unknown toolbar item "${l}"`);
|
|
3274
3403
|
return;
|
|
3275
3404
|
}
|
|
3276
|
-
const
|
|
3277
|
-
Array.isArray(
|
|
3405
|
+
const o = n();
|
|
3406
|
+
Array.isArray(o) ? s.push(...o) : s.push(o);
|
|
3278
3407
|
}), s.length && this.toolbar.appendChild(this.group(...s));
|
|
3279
|
-
}), this.tbrMore = this.tbtn(
|
|
3408
|
+
}), this.tbrMore = this.tbtn(c.more, this.t("more"), () => {
|
|
3280
3409
|
this.tbrExpanded = !this.tbrExpanded, this.updateToolbarOverflow();
|
|
3281
3410
|
}), this.tbrMore.classList.add("tbr-more"), this.toolbar.appendChild(this.tbrMore), this.syncColorSwatches(this.toolbar), this.updateToolbarOverflow();
|
|
3282
3411
|
}
|
|
@@ -3306,134 +3435,134 @@ const I = class I {
|
|
|
3306
3435
|
this.menubar.innerHTML = "";
|
|
3307
3436
|
const t = {
|
|
3308
3437
|
file: [
|
|
3309
|
-
this.mItem("newdoc",
|
|
3438
|
+
this.mItem("newdoc", c.newic, () => {
|
|
3310
3439
|
this.recordRevision(), this.ed.innerHTML = "<p><br></p>", this.onChange();
|
|
3311
3440
|
}),
|
|
3312
3441
|
"|",
|
|
3313
|
-
this.mItem("importword",
|
|
3314
|
-
this.mItem("restoredraft",
|
|
3442
|
+
this.mItem("importword", c.wordic, () => this.pickWordDoc()),
|
|
3443
|
+
this.mItem("restoredraft", c.draftic, () => {
|
|
3315
3444
|
this.restoreDraft() || alert(this.t("draftempty"));
|
|
3316
3445
|
}),
|
|
3317
|
-
this.mItem("revhistory",
|
|
3446
|
+
this.mItem("revhistory", c.historyic, () => this.revisionDlg()),
|
|
3318
3447
|
"|",
|
|
3319
|
-
this.mItem("preview",
|
|
3320
|
-
this.mItem("print",
|
|
3448
|
+
this.mItem("preview", c.prevw, () => this.previewDlg()),
|
|
3449
|
+
this.mItem("print", c.printic, () => this.printDoc(), "Ctrl+P")
|
|
3321
3450
|
],
|
|
3322
3451
|
edit: [
|
|
3323
|
-
this.mItem("undo",
|
|
3324
|
-
this.mItem("redo",
|
|
3452
|
+
this.mItem("undo", c.undo, () => this.exec("undo"), "Ctrl+Z"),
|
|
3453
|
+
this.mItem("redo", c.redo, () => this.exec("redo"), "Ctrl+Y"),
|
|
3325
3454
|
"|",
|
|
3326
|
-
this.mItem("cut",
|
|
3327
|
-
this.mItem("copy",
|
|
3328
|
-
this.mItem("paste",
|
|
3455
|
+
this.mItem("cut", c.cutic, () => this.exec("cut"), "Ctrl+X"),
|
|
3456
|
+
this.mItem("copy", c.copyic, () => this.exec("copy"), "Ctrl+C"),
|
|
3457
|
+
this.mItem("paste", c.pasteic, () => alert(this.t("pastehint")), "Ctrl+V"),
|
|
3329
3458
|
"|",
|
|
3330
|
-
this.mItem("selectall",
|
|
3459
|
+
this.mItem("selectall", c.selall, () => this.exec("selectAll"), "Ctrl+A")
|
|
3331
3460
|
],
|
|
3332
3461
|
view: [
|
|
3333
|
-
this.mItem("fullscreen",
|
|
3334
|
-
this.mItem("preview",
|
|
3335
|
-
this.mItem("sourcecode",
|
|
3462
|
+
this.mItem("fullscreen", c.fullscreen, () => this.toggleFullscreen()),
|
|
3463
|
+
this.mItem("preview", c.prevw, () => this.previewDlg()),
|
|
3464
|
+
this.mItem("sourcecode", c.srcic, () => this.sourceDlg())
|
|
3336
3465
|
],
|
|
3337
3466
|
insert: [
|
|
3338
|
-
this.mItem("link",
|
|
3339
|
-
this.mItem("image",
|
|
3340
|
-
this.mItem("video",
|
|
3341
|
-
{ label: this.t("inserttable"), icon:
|
|
3342
|
-
this.mItem("codesample",
|
|
3343
|
-
{ label: this.t("template"), icon:
|
|
3344
|
-
this.mItem("hr",
|
|
3467
|
+
this.mItem("link", c.link, () => this.linkDlg()),
|
|
3468
|
+
this.mItem("image", c.image, () => this.insertImagePlaceholder()),
|
|
3469
|
+
this.mItem("video", c.video, () => this.videoDlg()),
|
|
3470
|
+
{ label: this.t("inserttable"), icon: c.tableic, action: () => this.tableGrid(this.menubar.querySelector('[data-menu-key="table"]') || this.menubar) },
|
|
3471
|
+
this.mItem("codesample", c.codesampleic, () => this.codeDlg()),
|
|
3472
|
+
{ label: this.t("template"), icon: c.templateic, subBuild: (s) => this.buildTemplatePickInto(s) },
|
|
3473
|
+
this.mItem("hr", c.hric, () => this.exec("insertHorizontalRule")),
|
|
3345
3474
|
"|",
|
|
3346
|
-
this.mItem("charmap",
|
|
3347
|
-
this.mItem("emoji",
|
|
3475
|
+
this.mItem("charmap", c.charic, () => this.charMap()),
|
|
3476
|
+
this.mItem("emoji", c.emojiic, () => this.emojiMap()),
|
|
3348
3477
|
this.mItem(
|
|
3349
3478
|
"datetime",
|
|
3350
|
-
|
|
3479
|
+
c.dateic,
|
|
3351
3480
|
() => this.exec("insertText", (/* @__PURE__ */ new Date()).toLocaleString(this.lang === "ar" ? "ar-AE" : "en-GB"))
|
|
3352
3481
|
),
|
|
3353
3482
|
"|",
|
|
3354
3483
|
{
|
|
3355
3484
|
label: this.t("pagebreak"),
|
|
3356
|
-
icon:
|
|
3485
|
+
icon: c.pbic,
|
|
3357
3486
|
action: () => {
|
|
3358
3487
|
this.restoreSel(), document.execCommand("insertHTML", !1, '<hr class="pagebreak"><p><br></p>'), this.onChange();
|
|
3359
3488
|
}
|
|
3360
3489
|
},
|
|
3361
|
-
this.mItem("nbsp",
|
|
3490
|
+
this.mItem("nbsp", c.nbspic, () => this.exec("insertText", " "))
|
|
3362
3491
|
],
|
|
3363
3492
|
format: [
|
|
3364
|
-
this.mItem("bold",
|
|
3365
|
-
this.mItem("italic",
|
|
3366
|
-
this.mItem("underline",
|
|
3367
|
-
this.mItem("strikethrough",
|
|
3368
|
-
this.mItem("superscript",
|
|
3369
|
-
this.mItem("subscript",
|
|
3370
|
-
this.mItem("code",
|
|
3371
|
-
this.mItem("quote",
|
|
3493
|
+
this.mItem("bold", c.bold, () => this.exec("bold"), "Ctrl+B"),
|
|
3494
|
+
this.mItem("italic", c.italic, () => this.exec("italic"), "Ctrl+I"),
|
|
3495
|
+
this.mItem("underline", c.underline, () => this.exec("underline"), "Ctrl+U"),
|
|
3496
|
+
this.mItem("strikethrough", c.strikethrough, () => this.exec("strikeThrough")),
|
|
3497
|
+
this.mItem("superscript", c.superscriptic, () => this.exec("superscript")),
|
|
3498
|
+
this.mItem("subscript", c.subscriptic, () => this.exec("subscript")),
|
|
3499
|
+
this.mItem("code", c.inlinecodeic, () => this.toggleInlineCode()),
|
|
3500
|
+
this.mItem("quote", c.quote, () => this.toggleBlock("blockquote")),
|
|
3372
3501
|
"|",
|
|
3373
3502
|
{ label: this.t("fontfamily"), subBuild: (s) => this.menuItems(s, this.fontItems()) },
|
|
3374
3503
|
{ label: this.t("fontsize"), subBuild: (s) => this.menuItems(s, this.sizeItems()) },
|
|
3375
3504
|
{ label: this.t("blocks"), subBuild: (s) => this.menuItems(s, this.blockItems()) },
|
|
3376
3505
|
{ label: this.t("align"), subBuild: (s) => this.menuItems(s, this.alignItems()) },
|
|
3377
|
-
{ label: this.t("lineheight"), icon:
|
|
3378
|
-
{ label: this.t("wordspacing"), icon:
|
|
3379
|
-
{ label: this.t("letterspacing"), icon:
|
|
3506
|
+
{ label: this.t("lineheight"), icon: c.lineheight, subBuild: (s) => this.menuItems(s, this.blockStyleItems("lineHeight", U)) },
|
|
3507
|
+
{ label: this.t("wordspacing"), icon: c.wordspacing, subBuild: (s) => this.menuItems(s, this.blockStyleItems("wordSpacing", W)) },
|
|
3508
|
+
{ label: this.t("letterspacing"), icon: c.letterspacing, subBuild: (s) => this.menuItems(s, this.blockStyleItems("letterSpacing", j)) },
|
|
3380
3509
|
"|",
|
|
3381
|
-
{ label: this.t("forecolor"), icon:
|
|
3382
|
-
{ label: this.t("backcolor"), icon:
|
|
3510
|
+
{ label: this.t("forecolor"), icon: c.palette, subBuild: (s) => this.buildPaletteInto(s, this.foreColor, (l) => this.applyColor("fore", l)) },
|
|
3511
|
+
{ label: this.t("backcolor"), icon: c.backcolor, subBuild: (s) => this.buildPaletteInto(s, this.backColor, (l) => this.applyColor("back", l)) },
|
|
3383
3512
|
"|",
|
|
3384
|
-
this.mItem("bullist",
|
|
3385
|
-
this.mItem("numlist",
|
|
3386
|
-
this.mItem("outdent",
|
|
3387
|
-
this.mItem("indent",
|
|
3513
|
+
this.mItem("bullist", c.bullist, () => this.exec("insertUnorderedList")),
|
|
3514
|
+
this.mItem("numlist", c.numlist, () => this.exec("insertOrderedList")),
|
|
3515
|
+
this.mItem("outdent", c.outdent, () => this.exec("outdent")),
|
|
3516
|
+
this.mItem("indent", c.indent, () => this.exec("indent")),
|
|
3388
3517
|
"|",
|
|
3389
|
-
this.mItem("ltr",
|
|
3390
|
-
this.mItem("rtl",
|
|
3518
|
+
this.mItem("ltr", c.ltr, () => this.setDir("ltr")),
|
|
3519
|
+
this.mItem("rtl", c.rtl, () => this.setDir("rtl")),
|
|
3391
3520
|
"|",
|
|
3392
|
-
{ label: this.t("changecase"), icon:
|
|
3521
|
+
{ label: this.t("changecase"), icon: c.caseic, sub: this.caseItems() },
|
|
3393
3522
|
"|",
|
|
3394
|
-
this.mItem("clearformat",
|
|
3523
|
+
this.mItem("clearformat", c.clearformatic, () => this.exec("removeFormat"))
|
|
3395
3524
|
],
|
|
3396
|
-
tools: [this.mItem("sourcecode",
|
|
3525
|
+
tools: [this.mItem("sourcecode", c.srcic, () => this.sourceDlg()), this.mItem("wordcount", c.wcic, () => this.wordCountDlg())],
|
|
3397
3526
|
table: [
|
|
3398
|
-
{ label: this.t("inserttable"), icon:
|
|
3527
|
+
{ label: this.t("inserttable"), icon: c.tableic, subBuild: (s) => this.buildTableGridInto(s) },
|
|
3399
3528
|
"|",
|
|
3400
3529
|
{
|
|
3401
3530
|
label: this.t("cell"),
|
|
3402
3531
|
sub: [
|
|
3403
|
-
{ label: this.t("cellprops"), icon:
|
|
3404
|
-
{ label: this.t("cellbg"), icon:
|
|
3532
|
+
{ label: this.t("cellprops"), icon: c.tableic, action: () => this.cellPropsDlg() },
|
|
3533
|
+
{ label: this.t("cellbg"), icon: c.palette, subBuild: (s) => this.buildCellFillInto(s) }
|
|
3405
3534
|
]
|
|
3406
3535
|
},
|
|
3407
3536
|
{
|
|
3408
3537
|
label: this.t("row"),
|
|
3409
3538
|
sub: [
|
|
3410
|
-
{ label: this.t("rowabove"), icon:
|
|
3411
|
-
{ label: this.t("rowbelow"), icon:
|
|
3412
|
-
{ label: this.t("delrow"), icon:
|
|
3539
|
+
{ label: this.t("rowabove"), icon: c.rowbefore, action: () => this.tableOp("rowabove"), hover: (s) => this.setOpTarget(s ? "row" : null) },
|
|
3540
|
+
{ label: this.t("rowbelow"), icon: c.rowafter, action: () => this.tableOp("rowbelow"), hover: (s) => this.setOpTarget(s ? "row" : null) },
|
|
3541
|
+
{ label: this.t("delrow"), icon: c.rowdelete, action: () => this.tableOp("delrow"), hover: (s) => this.setOpTarget(s ? "row" : null) },
|
|
3413
3542
|
"|",
|
|
3414
|
-
{ label: this.t("moverowup"), icon:
|
|
3415
|
-
{ label: this.t("moverowdown"), icon:
|
|
3543
|
+
{ label: this.t("moverowup"), icon: c.moverowup, action: () => this.tableMove("rowup"), hover: (s) => this.setOpTarget(s ? "row" : null) },
|
|
3544
|
+
{ label: this.t("moverowdown"), icon: c.moverowdown, action: () => this.tableMove("rowdown"), hover: (s) => this.setOpTarget(s ? "row" : null) },
|
|
3416
3545
|
"|",
|
|
3417
|
-
{ label: this.t("rowprops"), icon:
|
|
3546
|
+
{ label: this.t("rowprops"), icon: c.tableic, action: () => this.rowPropsDlg(), hover: (s) => this.setOpTarget(s ? "row" : null) }
|
|
3418
3547
|
]
|
|
3419
3548
|
},
|
|
3420
3549
|
{
|
|
3421
3550
|
label: this.t("column"),
|
|
3422
3551
|
sub: [
|
|
3423
|
-
{ label: this.t("colbefore"), icon:
|
|
3424
|
-
{ label: this.t("colafter"), icon:
|
|
3425
|
-
{ label: this.t("delcol"), icon:
|
|
3552
|
+
{ label: this.t("colbefore"), icon: c.colbefore, action: () => this.tableOp("colbefore"), hover: (s) => this.setOpTarget(s ? "col" : null) },
|
|
3553
|
+
{ label: this.t("colafter"), icon: c.colafter, action: () => this.tableOp("colafter"), hover: (s) => this.setOpTarget(s ? "col" : null) },
|
|
3554
|
+
{ label: this.t("delcol"), icon: c.coldelete, action: () => this.tableOp("delcol"), hover: (s) => this.setOpTarget(s ? "col" : null) },
|
|
3426
3555
|
"|",
|
|
3427
|
-
{ label: this.t("movecolleft"), icon:
|
|
3428
|
-
{ label: this.t("movecolright"), icon:
|
|
3556
|
+
{ label: this.t("movecolleft"), icon: c.movecolleft, action: () => this.tableMove("colleft"), hover: (s) => this.setOpTarget(s ? "col" : null) },
|
|
3557
|
+
{ label: this.t("movecolright"), icon: c.movecolright, action: () => this.tableMove("colright"), hover: (s) => this.setOpTarget(s ? "col" : null) },
|
|
3429
3558
|
"|",
|
|
3430
|
-
{ label: this.t("colprops"), icon:
|
|
3559
|
+
{ label: this.t("colprops"), icon: c.tableic, action: () => this.colPropsDlg(), hover: (s) => this.setOpTarget(s ? "col" : null) }
|
|
3431
3560
|
]
|
|
3432
3561
|
},
|
|
3433
3562
|
"|",
|
|
3434
3563
|
{
|
|
3435
3564
|
label: this.t("tablepropsttl"),
|
|
3436
|
-
icon:
|
|
3565
|
+
icon: c.tableic,
|
|
3437
3566
|
action: () => {
|
|
3438
3567
|
const s = this.currentCell();
|
|
3439
3568
|
if (!s) {
|
|
@@ -3443,10 +3572,10 @@ const I = class I {
|
|
|
3443
3572
|
this.tblActive = s.closest("table"), this.tablePropsDlg();
|
|
3444
3573
|
}
|
|
3445
3574
|
},
|
|
3446
|
-
{ label: this.t("deltable"), icon:
|
|
3575
|
+
{ label: this.t("deltable"), icon: c.trash, action: () => this.tableOp("deltable") }
|
|
3447
3576
|
],
|
|
3448
|
-
help: [this.mItem("helpttl",
|
|
3449
|
-
}, e = this.options.menubar === !0 ?
|
|
3577
|
+
help: [this.mItem("helpttl", c.helpic, () => this.helpDlg(), "Alt+0")]
|
|
3578
|
+
}, e = this.options.menubar === !0 ? ct : this.options.menubar, i = /* @__PURE__ */ new Set();
|
|
3450
3579
|
e.split(/\s+/).filter(Boolean).forEach((s) => {
|
|
3451
3580
|
if (i.has(s)) return;
|
|
3452
3581
|
if (i.add(s), !t[s]) {
|
|
@@ -3454,36 +3583,36 @@ const I = class I {
|
|
|
3454
3583
|
return;
|
|
3455
3584
|
}
|
|
3456
3585
|
const l = document.createElement("button");
|
|
3457
|
-
l.type = "button", l.textContent = this.t(s), l.dataset.menuKey = s, l.addEventListener("mousedown", (
|
|
3458
|
-
|
|
3459
|
-
}), l.addEventListener("click", () => this.popup(l, (
|
|
3586
|
+
l.type = "button", l.textContent = this.t(s), l.dataset.menuKey = s, l.addEventListener("mousedown", (n) => {
|
|
3587
|
+
n.preventDefault(), this.saveSel();
|
|
3588
|
+
}), l.addEventListener("click", () => this.popup(l, (n) => this.menuItems(n, t[s]))), this.menubar.appendChild(l);
|
|
3460
3589
|
});
|
|
3461
3590
|
}
|
|
3462
3591
|
/* ---------------------------------------------------------- table ops */
|
|
3463
3592
|
tableOp(t) {
|
|
3464
|
-
var r,
|
|
3593
|
+
var r, a, h;
|
|
3465
3594
|
this.restoreSel();
|
|
3466
3595
|
const e = window.getSelection();
|
|
3467
3596
|
if (!e) return;
|
|
3468
|
-
const i = ((r = this.closestBlock(e.anchorNode)) == null ? void 0 : r.closest("td,th")) || (e.anchorNode && e.anchorNode.nodeType === 1 ? (h = (
|
|
3597
|
+
const i = ((r = this.closestBlock(e.anchorNode)) == null ? void 0 : r.closest("td,th")) || (e.anchorNode && e.anchorNode.nodeType === 1 ? (h = (a = e.anchorNode).closest) == null ? void 0 : h.call(a, "td,th") : null);
|
|
3469
3598
|
if (!i) return;
|
|
3470
|
-
const s = i.parentElement, l = i.closest("table"),
|
|
3471
|
-
const
|
|
3599
|
+
const s = i.parentElement, l = i.closest("table"), n = Array.from(s.children).indexOf(i), o = () => {
|
|
3600
|
+
const p = s.cloneNode(!1);
|
|
3472
3601
|
return Array.from(s.children).forEach((m) => {
|
|
3473
3602
|
const g = document.createElement("td"), u = m.getAttribute("style");
|
|
3474
|
-
u && g.setAttribute("style", u), g.style.removeProperty("background-color"), g.innerHTML = "<br>",
|
|
3475
|
-
}),
|
|
3603
|
+
u && g.setAttribute("style", u), g.style.removeProperty("background-color"), g.innerHTML = "<br>", p.appendChild(g);
|
|
3604
|
+
}), p;
|
|
3476
3605
|
};
|
|
3477
|
-
if (t === "rowabove" && s.before(
|
|
3478
|
-
const
|
|
3479
|
-
s.remove(),
|
|
3606
|
+
if (t === "rowabove" && s.before(o()), t === "rowbelow" && s.after(o()), t === "delrow") {
|
|
3607
|
+
const p = s.parentElement;
|
|
3608
|
+
s.remove(), p.querySelector("tr") || l.remove();
|
|
3480
3609
|
}
|
|
3481
|
-
(t === "colbefore" || t === "colafter") && l.querySelectorAll("tr").forEach((
|
|
3482
|
-
const m =
|
|
3610
|
+
(t === "colbefore" || t === "colafter") && l.querySelectorAll("tr").forEach((p) => {
|
|
3611
|
+
const m = p.children[Math.min(n, p.children.length - 1)], g = document.createElement("td"), u = m.getAttribute("style");
|
|
3483
3612
|
u && g.setAttribute("style", u), g.style.removeProperty("width"), g.style.removeProperty("background-color"), g.innerHTML = "<br>", t === "colbefore" ? m.before(g) : m.after(g);
|
|
3484
|
-
}), t === "delcol" && (l.querySelectorAll("tr").forEach((
|
|
3613
|
+
}), t === "delcol" && (l.querySelectorAll("tr").forEach((p) => {
|
|
3485
3614
|
var m;
|
|
3486
|
-
return (m =
|
|
3615
|
+
return (m = p.children[n]) == null ? void 0 : m.remove();
|
|
3487
3616
|
}), l.querySelector("td,th") || l.remove()), t === "deltable" && l.remove(), this.onChange(), this.positionTableHandles();
|
|
3488
3617
|
}
|
|
3489
3618
|
/** Reorders the current row/column: 'rowup'/'rowdown' swap the caret's row with
|
|
@@ -3503,16 +3632,16 @@ const I = class I {
|
|
|
3503
3632
|
r && r.after(i);
|
|
3504
3633
|
}
|
|
3505
3634
|
t === "colleft" && l > 0 && s.querySelectorAll("tr").forEach((r) => {
|
|
3506
|
-
const
|
|
3507
|
-
|
|
3635
|
+
const a = r.children[l], h = r.children[l - 1];
|
|
3636
|
+
a && h && h.before(a);
|
|
3508
3637
|
}), t === "colright" && s.querySelectorAll("tr").forEach((r) => {
|
|
3509
|
-
const
|
|
3510
|
-
|
|
3638
|
+
const a = r.children[l], h = r.children[l + 1];
|
|
3639
|
+
a && h && h.after(a);
|
|
3511
3640
|
});
|
|
3512
|
-
const
|
|
3513
|
-
|
|
3514
|
-
const
|
|
3515
|
-
|
|
3641
|
+
const n = document.createRange();
|
|
3642
|
+
n.selectNodeContents(e), n.collapse(!0);
|
|
3643
|
+
const o = window.getSelection();
|
|
3644
|
+
o && (o.removeAllRanges(), o.addRange(n)), this.saveSel(), this.onChange(), this.positionTableHandles(), this.positionCellMarker();
|
|
3516
3645
|
}
|
|
3517
3646
|
/** Align the whole table via auto margins — same semantics as the align
|
|
3518
3647
|
* field in the table-properties dialog. */
|
|
@@ -3549,26 +3678,26 @@ const I = class I {
|
|
|
3549
3678
|
tablePropsDlg() {
|
|
3550
3679
|
const t = this.tblActive;
|
|
3551
3680
|
if (!t) return;
|
|
3552
|
-
let e, i, s, l,
|
|
3553
|
-
const
|
|
3681
|
+
let e, i, s, l, n;
|
|
3682
|
+
const o = "display:flex;align-items:center;gap:10px;margin:10px 0", r = "width:120px;color:#556;flex:none", a = "flex:1;border:1px solid #cfd6df;border-radius:6px;padding:7px 9px;font:14px inherit", h = t.querySelector("td,th"), p = t.style.width || "", m = h && h.style.padding ? parseFloat(h.style.padding) : "", g = t.style.borderSpacing ? parseFloat(t.style.borderSpacing) : "", u = t.style.borderWidth ? parseFloat(t.style.borderWidth) : "", v = t.style.marginLeft, b = t.style.marginRight, x = v === "auto" && b === "auto" ? "center" : v === "auto" ? "right" : b === "auto" && v === "0" ? "left" : "";
|
|
3554
3683
|
this.dialog(
|
|
3555
3684
|
this.t("tablepropsttl"),
|
|
3556
3685
|
(C) => {
|
|
3557
|
-
const
|
|
3686
|
+
const S = (w, k) => {
|
|
3558
3687
|
const L = document.createElement("div");
|
|
3559
|
-
L.style.cssText =
|
|
3688
|
+
L.style.cssText = o;
|
|
3560
3689
|
const H = document.createElement("span");
|
|
3561
3690
|
H.style.cssText = r, H.textContent = this.t(w), L.append(H, k), C.appendChild(L);
|
|
3562
3691
|
};
|
|
3563
|
-
e = document.createElement("input"), e.type = "text", e.style.cssText =
|
|
3692
|
+
e = document.createElement("input"), e.type = "text", e.style.cssText = a, e.placeholder = "e.g. 600px or 100%", e.value = p, S("tblwidth", e), i = document.createElement("input"), i.type = "number", i.min = "0", i.style.cssText = a, i.value = String(m), S("tblcellpadding", i), s = document.createElement("input"), s.type = "number", s.min = "0", s.style.cssText = a, s.value = String(g), S("tblcellspacing", s), l = document.createElement("input"), l.type = "number", l.min = "0", l.style.cssText = a, l.value = String(u), S("tblborder", l), n = document.createElement("select"), n.style.cssText = a, [
|
|
3564
3693
|
["", "alignnone"],
|
|
3565
3694
|
["left", "alignleft"],
|
|
3566
3695
|
["center", "aligncenter"],
|
|
3567
3696
|
["right", "alignright"]
|
|
3568
3697
|
].forEach(([w, k]) => {
|
|
3569
3698
|
const L = document.createElement("option");
|
|
3570
|
-
L.value = w, L.textContent = this.t(k), w === x && (L.selected = !0),
|
|
3571
|
-
}),
|
|
3699
|
+
L.value = w, L.textContent = this.t(k), w === x && (L.selected = !0), n.appendChild(L);
|
|
3700
|
+
}), S("tblalign", n);
|
|
3572
3701
|
},
|
|
3573
3702
|
[
|
|
3574
3703
|
{ label: this.t("cancel"), action: () => this.closeDlg() },
|
|
@@ -3581,7 +3710,7 @@ const I = class I {
|
|
|
3581
3710
|
cellpadding: i.value.trim(),
|
|
3582
3711
|
cellspacing: s.value.trim(),
|
|
3583
3712
|
border: l.value.trim(),
|
|
3584
|
-
align:
|
|
3713
|
+
align: n.value
|
|
3585
3714
|
}), this.closeDlg(), this.onChange(), this.positionTableHandles();
|
|
3586
3715
|
}
|
|
3587
3716
|
}
|
|
@@ -3620,8 +3749,8 @@ const I = class I {
|
|
|
3620
3749
|
formSelect(t, e) {
|
|
3621
3750
|
const i = document.createElement("select");
|
|
3622
3751
|
return i.style.cssText = "flex:1;border:1px solid #cfd6df;border-radius:6px;padding:7px 9px;font:14px inherit;background:#fff", t.forEach(([s, l]) => {
|
|
3623
|
-
const
|
|
3624
|
-
|
|
3752
|
+
const n = document.createElement("option");
|
|
3753
|
+
n.value = s, n.textContent = l, s === e && (n.selected = !0), i.appendChild(n);
|
|
3625
3754
|
}), i;
|
|
3626
3755
|
}
|
|
3627
3756
|
formBg(t) {
|
|
@@ -3631,8 +3760,8 @@ const I = class I {
|
|
|
3631
3760
|
s.type = "color", s.value = i || "#ffffff", s.style.cssText = "width:36px;height:29px;border:1px solid #cfd6df;border-radius:4px;padding:1px;background:none;cursor:pointer";
|
|
3632
3761
|
const l = document.createElement("label");
|
|
3633
3762
|
l.style.cssText = "display:flex;align-items:center;gap:6px;cursor:pointer;color:#556";
|
|
3634
|
-
const
|
|
3635
|
-
return
|
|
3763
|
+
const n = document.createElement("input");
|
|
3764
|
+
return n.type = "checkbox", n.checked = !!i, l.append(n, document.createTextNode(this.t("fill"))), s.addEventListener("input", () => n.checked = !0), e.append(s, l), { wrap: e, color: s, fill: n };
|
|
3636
3765
|
}
|
|
3637
3766
|
setOrClear(t, e, i) {
|
|
3638
3767
|
i ? t.style.setProperty(e, /^(width|height)$/.test(e) && /^\d+$/.test(i) ? i + "px" : i) : t.style.removeProperty(e);
|
|
@@ -3643,11 +3772,11 @@ const I = class I {
|
|
|
3643
3772
|
alert(this.t("nocell"));
|
|
3644
3773
|
return;
|
|
3645
3774
|
}
|
|
3646
|
-
let e, i, s, l,
|
|
3775
|
+
let e, i, s, l, n;
|
|
3647
3776
|
this.dialog(
|
|
3648
3777
|
this.t("cellprops").replace("…", ""),
|
|
3649
|
-
(
|
|
3650
|
-
e = this.formInput(t.style.width, "e.g. 120px / 25%"), this.formRow(
|
|
3778
|
+
(o) => {
|
|
3779
|
+
e = this.formInput(t.style.width, "e.g. 120px / 25%"), this.formRow(o, this.t("tblwidth"), e), i = this.formInput(t.style.height, "e.g. 40px"), this.formRow(o, this.t("tblheight"), i), s = this.formSelect(
|
|
3651
3780
|
[
|
|
3652
3781
|
["", this.t("alignnone")],
|
|
3653
3782
|
["left", this.t("alignleft")],
|
|
@@ -3655,7 +3784,7 @@ const I = class I {
|
|
|
3655
3784
|
["right", this.t("alignright")]
|
|
3656
3785
|
],
|
|
3657
3786
|
t.style.textAlign || ""
|
|
3658
|
-
), this.formRow(
|
|
3787
|
+
), this.formRow(o, this.t("tblalign"), s), l = this.formSelect(
|
|
3659
3788
|
[
|
|
3660
3789
|
["", this.t("alignnone")],
|
|
3661
3790
|
["top", this.t("valigntop")],
|
|
@@ -3663,7 +3792,7 @@ const I = class I {
|
|
|
3663
3792
|
["bottom", this.t("valignbottom")]
|
|
3664
3793
|
],
|
|
3665
3794
|
t.style.verticalAlign || ""
|
|
3666
|
-
), this.formRow(
|
|
3795
|
+
), this.formRow(o, this.t("valign"), l), n = this.formBg(t.style.backgroundColor || ""), this.formRow(o, this.t("backcolor"), n.wrap);
|
|
3667
3796
|
},
|
|
3668
3797
|
[
|
|
3669
3798
|
{ label: this.t("cancel"), action: () => this.closeDlg() },
|
|
@@ -3671,7 +3800,7 @@ const I = class I {
|
|
|
3671
3800
|
label: this.t("save"),
|
|
3672
3801
|
primary: !0,
|
|
3673
3802
|
action: () => {
|
|
3674
|
-
this.setOrClear(t, "width", e.value.trim()), this.setOrClear(t, "height", i.value.trim()), this.setOrClear(t, "text-align", s.value), this.setOrClear(t, "vertical-align", l.value), this.setOrClear(t, "background-color",
|
|
3803
|
+
this.setOrClear(t, "width", e.value.trim()), this.setOrClear(t, "height", i.value.trim()), this.setOrClear(t, "text-align", s.value), this.setOrClear(t, "vertical-align", l.value), this.setOrClear(t, "background-color", n.fill.checked ? n.color.value : ""), this.closeDlg(), this.onChange(), this.positionTableHandles();
|
|
3675
3804
|
}
|
|
3676
3805
|
}
|
|
3677
3806
|
]
|
|
@@ -3709,11 +3838,11 @@ const I = class I {
|
|
|
3709
3838
|
return;
|
|
3710
3839
|
}
|
|
3711
3840
|
const e = t.parentElement, i = t.closest("table"), s = Array.from(e.children).indexOf(t), l = Array.from(i.rows).map((r) => r.cells[s]).filter(Boolean);
|
|
3712
|
-
let
|
|
3841
|
+
let n, o;
|
|
3713
3842
|
this.dialog(
|
|
3714
3843
|
this.t("colprops").replace("…", ""),
|
|
3715
3844
|
(r) => {
|
|
3716
|
-
|
|
3845
|
+
n = this.formInput(t.style.width, "e.g. 120px / 25%"), this.formRow(r, this.t("tblwidth"), n), o = this.formBg(t.style.backgroundColor || ""), this.formRow(r, this.t("backcolor"), o.wrap);
|
|
3717
3846
|
},
|
|
3718
3847
|
[
|
|
3719
3848
|
{ label: this.t("cancel"), action: () => this.closeDlg() },
|
|
@@ -3722,7 +3851,7 @@ const I = class I {
|
|
|
3722
3851
|
primary: !0,
|
|
3723
3852
|
action: () => {
|
|
3724
3853
|
l.forEach((r) => {
|
|
3725
|
-
this.setOrClear(r, "width",
|
|
3854
|
+
this.setOrClear(r, "width", n.value.trim()), this.setOrClear(r, "background-color", o.fill.checked ? o.color.value : "");
|
|
3726
3855
|
}), this.closeDlg(), this.onChange(), this.positionTableHandles();
|
|
3727
3856
|
}
|
|
3728
3857
|
}
|
|
@@ -3738,8 +3867,8 @@ const I = class I {
|
|
|
3738
3867
|
const s = document.createElement("div");
|
|
3739
3868
|
s.className = "dlg", s.dir = this.dir(), s.innerHTML = `<header><span>${t}</span><button type="button">×</button></header>
|
|
3740
3869
|
<div class="body"></div><footer></footer>`, s.querySelector("header button").onclick = () => this.closeDlg(), e(s.querySelector(".body")), (i || [{ label: this.t("close"), primary: !0, action: () => this.closeDlg() }]).forEach((l) => {
|
|
3741
|
-
const
|
|
3742
|
-
|
|
3870
|
+
const n = document.createElement("button");
|
|
3871
|
+
n.type = "button", n.textContent = l.label, l.primary && (n.className = "pri"), n.onclick = l.action, s.querySelector("footer").appendChild(n);
|
|
3743
3872
|
}), this.dlgOvl.appendChild(s), this.dlgOvl.addEventListener("mousedown", (l) => {
|
|
3744
3873
|
l.target === this.dlgOvl && this.closeDlg();
|
|
3745
3874
|
}), document.body.appendChild(this.dlgOvl);
|
|
@@ -3789,8 +3918,12 @@ const I = class I {
|
|
|
3789
3918
|
}
|
|
3790
3919
|
previewDlg() {
|
|
3791
3920
|
this.dialog(this.t("previewttl"), (t) => {
|
|
3921
|
+
var s;
|
|
3922
|
+
(s = t.closest(".dlg")) == null || s.classList.add("dlg-preview");
|
|
3792
3923
|
const e = document.createElement("div");
|
|
3793
|
-
e.
|
|
3924
|
+
e.className = "pv-box";
|
|
3925
|
+
const i = this.contentWidth();
|
|
3926
|
+
e.style.cssText = `width:${i > 0 ? Math.round(i) : 640}px;max-width:100%;max-height:52vh;overflow:auto;border:1px solid #e3e3e3;border-radius:6px;padding:14px;font-family:Helvetica,Arial,sans-serif;font-size:14px`, e.innerHTML = this.ed.innerHTML, t.appendChild(e);
|
|
3794
3927
|
});
|
|
3795
3928
|
}
|
|
3796
3929
|
/** Two-pane picker shared by the special-character map and the emoji map:
|
|
@@ -3799,31 +3932,31 @@ const I = class I {
|
|
|
3799
3932
|
this.saveSel(), this.dialog(t, (s) => {
|
|
3800
3933
|
const l = document.createElement("div");
|
|
3801
3934
|
l.className = "chmap";
|
|
3802
|
-
const o = document.createElement("div");
|
|
3803
|
-
o.className = "chtabs";
|
|
3804
3935
|
const n = document.createElement("div");
|
|
3805
|
-
n.className = "
|
|
3936
|
+
n.className = "chtabs";
|
|
3937
|
+
const o = document.createElement("div");
|
|
3938
|
+
o.className = "chpanel";
|
|
3806
3939
|
const r = document.createElement("div");
|
|
3807
|
-
r.className = "chgrid" + (i ? " emgrid" : ""),
|
|
3808
|
-
const
|
|
3809
|
-
|
|
3940
|
+
r.className = "chgrid" + (i ? " emgrid" : ""), o.appendChild(r);
|
|
3941
|
+
const a = (h) => {
|
|
3942
|
+
n.querySelectorAll("button").forEach((p, m) => p.classList.toggle("on", m === h)), r.innerHTML = "", e[h].chars.forEach((p) => {
|
|
3810
3943
|
const m = document.createElement("button");
|
|
3811
|
-
m.type = "button", m.textContent =
|
|
3812
|
-
this.closeDlg(), this.exec("insertText",
|
|
3944
|
+
m.type = "button", m.textContent = p, m.onclick = () => {
|
|
3945
|
+
this.closeDlg(), this.exec("insertText", p);
|
|
3813
3946
|
}, r.appendChild(m);
|
|
3814
|
-
}),
|
|
3947
|
+
}), o.scrollTop = 0;
|
|
3815
3948
|
};
|
|
3816
|
-
e.forEach((h,
|
|
3949
|
+
e.forEach((h, p) => {
|
|
3817
3950
|
const m = document.createElement("button");
|
|
3818
|
-
m.type = "button", m.textContent = this.t(h.key), m.addEventListener("click", () =>
|
|
3819
|
-
}), l.append(
|
|
3951
|
+
m.type = "button", m.textContent = this.t(h.key), m.addEventListener("click", () => a(p)), n.appendChild(m);
|
|
3952
|
+
}), l.append(n, o), s.appendChild(l), a(0);
|
|
3820
3953
|
});
|
|
3821
3954
|
}
|
|
3822
3955
|
charMap() {
|
|
3823
|
-
this.glyphPickerDlg(this.t("charmap").replace("…", ""),
|
|
3956
|
+
this.glyphPickerDlg(this.t("charmap").replace("…", ""), ft, !1);
|
|
3824
3957
|
}
|
|
3825
3958
|
emojiMap() {
|
|
3826
|
-
this.glyphPickerDlg(this.t("emoji").replace("…", ""),
|
|
3959
|
+
this.glyphPickerDlg(this.t("emoji").replace("…", ""), vt, !0);
|
|
3827
3960
|
}
|
|
3828
3961
|
printDoc() {
|
|
3829
3962
|
const t = window.open("", "_blank");
|
|
@@ -3836,7 +3969,7 @@ const I = class I {
|
|
|
3836
3969
|
}
|
|
3837
3970
|
/* ---------------------------------------------- image upload placeholder */
|
|
3838
3971
|
imgPhHTML(t) {
|
|
3839
|
-
return `<div class="img-ph"${t ? ` id="${t}"` : ""} contenteditable="false">${
|
|
3972
|
+
return `<div class="img-ph"${t ? ` id="${t}"` : ""} contenteditable="false">${c.image}<span>${this.t("dropimage")}</span></div>`;
|
|
3840
3973
|
}
|
|
3841
3974
|
insertImagePlaceholder() {
|
|
3842
3975
|
this.restoreSel();
|
|
@@ -3860,11 +3993,11 @@ const I = class I {
|
|
|
3860
3993
|
var e;
|
|
3861
3994
|
const t = this.phCtx;
|
|
3862
3995
|
t && (t.innerHTML = "", t.append(
|
|
3863
|
-
this.ctxBtn(
|
|
3996
|
+
this.ctxBtn(c.uploadic, this.t("uploadimg"), () => {
|
|
3864
3997
|
this.phUploadTarget = this.phActive, this.pickImage();
|
|
3865
3998
|
}),
|
|
3866
|
-
this.ctxBtn(
|
|
3867
|
-
), (e = this.phActive) != null && e.closest(".tpl-media") && t.append(this.ctxBtn(
|
|
3999
|
+
this.ctxBtn(c.link, this.t("imagelink"), () => this.renderPhCtxUrlInput())
|
|
4000
|
+
), (e = this.phActive) != null && e.closest(".tpl-media") && t.append(this.ctxBtn(c.video, this.t("quickvideo"), () => this.swapPlaceholderKind("video"))), t.append(this.ctxSep(), this.ctxBtn(c.trash, this.t("deleteimg"), () => this.removeImgPlaceholder())), this.positionImgPhCtx());
|
|
3868
4001
|
}
|
|
3869
4002
|
/** Swaps a template slot's placeholder between image and video kinds, so the
|
|
3870
4003
|
* same media slot can be filled with either. */
|
|
@@ -3885,17 +4018,17 @@ const I = class I {
|
|
|
3885
4018
|
const i = document.createElement("button");
|
|
3886
4019
|
i.type = "button", i.className = "txtbtn", i.textContent = this.t("insertimg");
|
|
3887
4020
|
const s = () => {
|
|
3888
|
-
const l = e.value.trim(),
|
|
3889
|
-
if (!
|
|
4021
|
+
const l = e.value.trim(), n = this.phActive;
|
|
4022
|
+
if (!n) return;
|
|
3890
4023
|
if (!/^(https?:|data:image\/|blob:)/i.test(l)) {
|
|
3891
4024
|
e.classList.add("err"), e.focus();
|
|
3892
4025
|
return;
|
|
3893
4026
|
}
|
|
3894
4027
|
i.disabled = !0, e.disabled = !0;
|
|
3895
|
-
const
|
|
3896
|
-
|
|
4028
|
+
const o = new Image();
|
|
4029
|
+
o.onload = () => this.replacePlaceholderWithImage(n, l, ""), o.onerror = () => {
|
|
3897
4030
|
i.disabled = !1, e.disabled = !1, e.classList.add("err"), e.focus();
|
|
3898
|
-
},
|
|
4031
|
+
}, o.src = l;
|
|
3899
4032
|
};
|
|
3900
4033
|
i.addEventListener("click", s), e.addEventListener("input", () => e.classList.remove("err")), e.addEventListener("keydown", (l) => {
|
|
3901
4034
|
l.key === "Enter" ? (l.preventDefault(), s()) : l.key === "Escape" && (l.stopPropagation(), this.renderPhCtxButtons());
|
|
@@ -3921,13 +4054,64 @@ const I = class I {
|
|
|
3921
4054
|
s && (s.textContent = this.t("uploading")), this.imageUploadHandler(t).then((l) => {
|
|
3922
4055
|
this.ed.contains(e) && this.replacePlaceholderWithImage(e, l, i);
|
|
3923
4056
|
}).catch((l) => {
|
|
3924
|
-
var
|
|
3925
|
-
this.ed.contains(e) && (e.classList.remove("uploading"), e.classList.add("upload-error"), s && (s.textContent = this.t("uploadfailed")), (
|
|
4057
|
+
var n;
|
|
4058
|
+
this.ed.contains(e) && (e.classList.remove("uploading"), e.classList.add("upload-error"), s && (s.textContent = this.t("uploadfailed")), (n = this.onImageUploadError) == null || n.call(this, l, t));
|
|
3926
4059
|
});
|
|
3927
4060
|
}
|
|
3928
4061
|
replacePlaceholderWithImage(t, e, i) {
|
|
3929
4062
|
const s = document.createElement("img");
|
|
3930
|
-
s.src = e, s.alt = "", i && (s.title = i), t.replaceWith(s), this.phActive === t && this.clearImgPlaceholderSel(), this.refreshState(), this.onChange();
|
|
4063
|
+
s.src = e, s.alt = "", i && (s.title = i), t.replaceWith(s), this.stampImageSize(s), this.phActive === t && this.clearImgPlaceholderSel(), this.refreshState(), this.onChange();
|
|
4064
|
+
}
|
|
4065
|
+
/** Width of the editor's text column — the width `.earea img { max-width:100% }`
|
|
4066
|
+
* clamps an oversized image to. */
|
|
4067
|
+
contentWidth() {
|
|
4068
|
+
const t = getComputedStyle(this.ed), e = (parseFloat(t.paddingLeft) || 0) + (parseFloat(t.paddingRight) || 0);
|
|
4069
|
+
return Math.max(0, this.ed.clientWidth - e);
|
|
4070
|
+
}
|
|
4071
|
+
/** Inserts an <img> through execCommand and stamps its size once it has decoded.
|
|
4072
|
+
* A throwaway id is the only way to get a handle on what insertHTML created. */
|
|
4073
|
+
insertImageHTML(t, e) {
|
|
4074
|
+
const i = "fable-img-" + Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
|
|
4075
|
+
document.execCommand(
|
|
4076
|
+
"insertHTML",
|
|
4077
|
+
!1,
|
|
4078
|
+
`<img id="${i}" src="${t}"${e ? ` title="${e}"` : ""} alt="">`
|
|
4079
|
+
);
|
|
4080
|
+
const s = this.ed.querySelector("#" + i);
|
|
4081
|
+
s && (s.removeAttribute("id"), this.stampImageSize(s));
|
|
4082
|
+
}
|
|
4083
|
+
/** Gives a newly inserted image an explicit size so it renders the same in the
|
|
4084
|
+
* editor, in Preview and in a sent email. Without it the image only looks right
|
|
4085
|
+
* inside `.earea`, whose `max-width:100%` rule exists nowhere else — which is why
|
|
4086
|
+
* the same picture came out at a different size once the mail was sent.
|
|
4087
|
+
* Leaves alone: images inside a template media slot (deliberately fluid) and any
|
|
4088
|
+
* image that already carries a size from its source. */
|
|
4089
|
+
stampImageSize(t, e) {
|
|
4090
|
+
const i = (l) => {
|
|
4091
|
+
e ? e(l) : l && this.onChange();
|
|
4092
|
+
}, s = () => {
|
|
4093
|
+
if (!this.ed.contains(t) || t.closest(".tpl-media") || t.getAttribute("width") || t.getAttribute("height") || t.style.width || t.style.height) return i(!1);
|
|
4094
|
+
const l = t.naturalWidth;
|
|
4095
|
+
if (!l) return i(!1);
|
|
4096
|
+
const n = this.contentWidth(), o = Math.round(n > 0 ? Math.min(l, n) : l);
|
|
4097
|
+
t.setAttribute("width", String(o)), t.style.width = o + "px", t.style.height = "auto", i(!0);
|
|
4098
|
+
};
|
|
4099
|
+
t.complete && t.naturalWidth ? s() : (t.addEventListener("load", s, { once: !0 }), t.addEventListener("error", () => i(!1), { once: !0 }));
|
|
4100
|
+
}
|
|
4101
|
+
/** Sizes images in content that arrived from outside the editor — a document saved
|
|
4102
|
+
* before the editor started recording image sizes. Without this such a document
|
|
4103
|
+
* keeps rendering at one size here and another in a sent mail. Images that already
|
|
4104
|
+
* carry a size, and template slots, are left alone, so content written by a
|
|
4105
|
+
* current version passes through untouched. Emits one change after the images have
|
|
4106
|
+
* settled rather than one per image, and none at all if nothing needed stamping. */
|
|
4107
|
+
stampExistingImages() {
|
|
4108
|
+
const t = Array.from(this.ed.querySelectorAll("img"));
|
|
4109
|
+
if (!t.length) return;
|
|
4110
|
+
let e = t.length, i = !1;
|
|
4111
|
+
const s = (l) => {
|
|
4112
|
+
l && (i = !0), --e === 0 && i && this.onChange();
|
|
4113
|
+
};
|
|
4114
|
+
t.forEach((l) => this.stampImageSize(l, s));
|
|
3931
4115
|
}
|
|
3932
4116
|
positionImgPhCtx() {
|
|
3933
4117
|
if (this.phActive && !document.body.contains(this.phActive)) {
|
|
@@ -3946,7 +4130,7 @@ const I = class I {
|
|
|
3946
4130
|
this.vidInput.value = "", this.vidInput.click();
|
|
3947
4131
|
}
|
|
3948
4132
|
vidPhHTML(t) {
|
|
3949
|
-
return `<div class="img-ph vid-ph"${t ? ` id="${t}"` : ""} contenteditable="false">${
|
|
4133
|
+
return `<div class="img-ph vid-ph"${t ? ` id="${t}"` : ""} contenteditable="false">${c.video}<span>${this.t("dropvideo")}</span></div>`;
|
|
3950
4134
|
}
|
|
3951
4135
|
insertVideoPlaceholder() {
|
|
3952
4136
|
this.restoreSel();
|
|
@@ -3970,11 +4154,11 @@ const I = class I {
|
|
|
3970
4154
|
var e;
|
|
3971
4155
|
const t = this.vphCtx;
|
|
3972
4156
|
t && (t.innerHTML = "", t.append(
|
|
3973
|
-
this.ctxBtn(
|
|
4157
|
+
this.ctxBtn(c.uploadic, this.t("uploadvideo"), () => {
|
|
3974
4158
|
this.vphUploadTarget = this.vphActive, this.pickVideo();
|
|
3975
4159
|
}),
|
|
3976
|
-
this.ctxBtn(
|
|
3977
|
-
), (e = this.vphActive) != null && e.closest(".tpl-media") && t.append(this.ctxBtn(
|
|
4160
|
+
this.ctxBtn(c.link, this.t("videolink"), () => this.renderVphCtxUrlInput())
|
|
4161
|
+
), (e = this.vphActive) != null && e.closest(".tpl-media") && t.append(this.ctxBtn(c.image, this.t("quickimage"), () => this.swapPlaceholderKind("image"))), t.append(this.ctxSep(), this.ctxBtn(c.trash, this.t("deletevideo"), () => this.removeVphPlaceholder())), this.positionVphCtx());
|
|
3978
4162
|
}
|
|
3979
4163
|
renderVphCtxUrlInput() {
|
|
3980
4164
|
const t = this.vphCtx;
|
|
@@ -3985,20 +4169,20 @@ const I = class I {
|
|
|
3985
4169
|
const i = document.createElement("button");
|
|
3986
4170
|
i.type = "button", i.className = "txtbtn", i.textContent = this.t("insertvideo");
|
|
3987
4171
|
const s = () => {
|
|
3988
|
-
const l = e.value.trim(),
|
|
3989
|
-
if (!
|
|
4172
|
+
const l = e.value.trim(), n = this.vphActive;
|
|
4173
|
+
if (!n) return;
|
|
3990
4174
|
if (!/^(https?:|data:video\/|blob:)/i.test(l)) {
|
|
3991
4175
|
e.classList.add("err"), e.focus();
|
|
3992
4176
|
return;
|
|
3993
4177
|
}
|
|
3994
|
-
const
|
|
3995
|
-
if (
|
|
3996
|
-
this.replacePlaceholderWithEmbed(
|
|
4178
|
+
const o = this.videoEmbedUrl(l);
|
|
4179
|
+
if (o) {
|
|
4180
|
+
this.replacePlaceholderWithEmbed(n, o);
|
|
3997
4181
|
return;
|
|
3998
4182
|
}
|
|
3999
4183
|
i.disabled = !0, e.disabled = !0;
|
|
4000
4184
|
const r = document.createElement("video");
|
|
4001
|
-
r.preload = "metadata", r.onloadedmetadata = () => this.replacePlaceholderWithVideo(
|
|
4185
|
+
r.preload = "metadata", r.onloadedmetadata = () => this.replacePlaceholderWithVideo(n, l, ""), r.onerror = () => {
|
|
4002
4186
|
i.disabled = !1, e.disabled = !1, e.classList.add("err"), e.focus();
|
|
4003
4187
|
}, r.src = l;
|
|
4004
4188
|
};
|
|
@@ -4026,8 +4210,8 @@ const I = class I {
|
|
|
4026
4210
|
s && (s.textContent = this.t("uploading")), this.videoUploadHandler(t).then((l) => {
|
|
4027
4211
|
this.ed.contains(e) && this.replacePlaceholderWithVideo(e, l, i);
|
|
4028
4212
|
}).catch((l) => {
|
|
4029
|
-
var
|
|
4030
|
-
this.ed.contains(e) && (e.classList.remove("uploading"), e.classList.add("upload-error"), s && (s.textContent = this.t("uploadfailed")), (
|
|
4213
|
+
var n;
|
|
4214
|
+
this.ed.contains(e) && (e.classList.remove("uploading"), e.classList.add("upload-error"), s && (s.textContent = this.t("uploadfailed")), (n = this.onVideoUploadError) == null || n.call(this, l, t));
|
|
4031
4215
|
});
|
|
4032
4216
|
}
|
|
4033
4217
|
replacePlaceholderWithVideo(t, e, i) {
|
|
@@ -4067,23 +4251,23 @@ const I = class I {
|
|
|
4067
4251
|
e.className = "imgctx", e.dir = this.dir();
|
|
4068
4252
|
const i = () => {
|
|
4069
4253
|
var h;
|
|
4070
|
-
const
|
|
4071
|
-
(h = this.vidCtx) == null || h.replaceWith(
|
|
4072
|
-
}, s = (
|
|
4073
|
-
this.setVideoAlign(t,
|
|
4074
|
-
}, l = t.style.float === "left",
|
|
4075
|
-
const g = this.ctxBtn(
|
|
4076
|
-
return g.classList.toggle("on",
|
|
4254
|
+
const a = this.buildVideoCtxToolbar(t);
|
|
4255
|
+
(h = this.vidCtx) == null || h.replaceWith(a), this.vidCtx = a, this.positionVidCtx();
|
|
4256
|
+
}, s = (a) => {
|
|
4257
|
+
this.setVideoAlign(t, a), i();
|
|
4258
|
+
}, l = t.style.float === "left", n = t.style.float === "right", o = !l && !n && t.style.marginLeft === "auto" && t.style.marginRight === "auto", r = (a, h, p, m) => {
|
|
4259
|
+
const g = this.ctxBtn(a, h, m);
|
|
4260
|
+
return g.classList.toggle("on", p), g;
|
|
4077
4261
|
};
|
|
4078
4262
|
return e.append(
|
|
4079
|
-
r(
|
|
4080
|
-
r(
|
|
4081
|
-
r(
|
|
4263
|
+
r(c.alignleft, this.t("alignleft"), l, () => s("left")),
|
|
4264
|
+
r(c.aligncenter, this.t("aligncenter"), o, () => s("center")),
|
|
4265
|
+
r(c.alignright, this.t("alignright"), n, () => s("right")),
|
|
4082
4266
|
this.ctxSep(),
|
|
4083
|
-
r(
|
|
4267
|
+
r(c.trash, this.t("deletevideo"), !1, () => {
|
|
4084
4268
|
t.remove(), this.clearVidHandles(), this.onChange();
|
|
4085
4269
|
})
|
|
4086
|
-
), e.addEventListener("mousedown", (
|
|
4270
|
+
), e.addEventListener("mousedown", (a) => a.preventDefault()), e.addEventListener("mouseenter", () => this.cancelVidHide()), e.addEventListener("mouseleave", () => {
|
|
4087
4271
|
this.cancelVidHide(), this.vidHideTimer = window.setTimeout(() => this.clearVidHandles(), 250);
|
|
4088
4272
|
}), document.body.appendChild(e), e;
|
|
4089
4273
|
}
|
|
@@ -4120,30 +4304,30 @@ const I = class I {
|
|
|
4120
4304
|
* (videoUploadHandler when configured, else inline base64). */
|
|
4121
4305
|
videoDlg() {
|
|
4122
4306
|
this.saveSel();
|
|
4123
|
-
let t, e, i, s, l,
|
|
4124
|
-
const
|
|
4125
|
-
const
|
|
4126
|
-
|
|
4307
|
+
let t, e, i, s, l, n;
|
|
4308
|
+
const o = (a, h) => {
|
|
4309
|
+
const p = document.createElement("div");
|
|
4310
|
+
p.className = "dfield";
|
|
4127
4311
|
const m = document.createElement("label");
|
|
4128
|
-
return m.textContent = this.t(
|
|
4312
|
+
return m.textContent = this.t(a), p.append(m, h), p;
|
|
4129
4313
|
}, r = () => {
|
|
4130
|
-
const
|
|
4131
|
-
return
|
|
4314
|
+
const a = document.createElement("input");
|
|
4315
|
+
return a.type = "url", a;
|
|
4132
4316
|
};
|
|
4133
4317
|
this.dialog(
|
|
4134
4318
|
this.t("videodlgttl"),
|
|
4135
|
-
(
|
|
4319
|
+
(a) => {
|
|
4136
4320
|
const h = document.createElement("div");
|
|
4137
4321
|
h.className = "dtabs";
|
|
4138
|
-
const
|
|
4322
|
+
const p = [], m = (v, b) => {
|
|
4139
4323
|
const x = document.createElement("button");
|
|
4140
4324
|
x.type = "button", x.textContent = this.t(v);
|
|
4141
4325
|
const C = document.createElement("div");
|
|
4142
4326
|
C.className = "dtabpanel", b(C);
|
|
4143
|
-
const
|
|
4144
|
-
|
|
4327
|
+
const S = p.length;
|
|
4328
|
+
p.push(C), x.addEventListener("click", () => g(S)), h.appendChild(x);
|
|
4145
4329
|
}, g = (v) => {
|
|
4146
|
-
h.querySelectorAll("button").forEach((b, x) => b.classList.toggle("on", x === v)),
|
|
4330
|
+
h.querySelectorAll("button").forEach((b, x) => b.classList.toggle("on", x === v)), p.forEach((b, x) => b.style.display = x === v ? "" : "none");
|
|
4147
4331
|
};
|
|
4148
4332
|
m("vidgeneral", (v) => {
|
|
4149
4333
|
t = r(), t.placeholder = this.t("videourlph");
|
|
@@ -4164,24 +4348,24 @@ const I = class I {
|
|
|
4164
4348
|
};
|
|
4165
4349
|
if (this.videoUploadHandler)
|
|
4166
4350
|
this.videoUploadHandler(w).then(k).catch((H) => {
|
|
4167
|
-
var
|
|
4168
|
-
x.disabled = !1, x.textContent = this.t("uploadfailed"), (
|
|
4351
|
+
var z;
|
|
4352
|
+
x.disabled = !1, x.textContent = this.t("uploadfailed"), (z = this.onVideoUploadError) == null || z.call(this, H, w);
|
|
4169
4353
|
});
|
|
4170
4354
|
else {
|
|
4171
4355
|
const H = new FileReader();
|
|
4172
4356
|
H.onload = () => k(H.result), H.readAsDataURL(w);
|
|
4173
4357
|
}
|
|
4174
|
-
}), b.append(t, x, C), t.style.flex = "1", v.appendChild(
|
|
4175
|
-
const
|
|
4176
|
-
|
|
4358
|
+
}), b.append(t, x, C), t.style.flex = "1", v.appendChild(o("vidsource", b));
|
|
4359
|
+
const S = document.createElement("div");
|
|
4360
|
+
S.className = "drow", e = document.createElement("input"), e.type = "number", e.value = "560", i = document.createElement("input"), i.type = "number", i.value = "314", S.append(o("tblwidth", e), o("tblheight", i)), v.appendChild(S);
|
|
4177
4361
|
}), m("vidembed", (v) => {
|
|
4178
4362
|
const b = document.createElement("p");
|
|
4179
4363
|
b.textContent = this.t("vidembedhint"), b.style.cssText = "margin:0 0 8px;color:#556;font-size:13.5px", s = document.createElement("textarea"), s.style.cssText = "width:100%;box-sizing:border-box;height:160px", v.append(b, s);
|
|
4180
4364
|
}), m("vidadvanced", (v) => {
|
|
4181
|
-
l = r(),
|
|
4365
|
+
l = r(), n = r(), v.append(o("vidaltsource", l), o("vidposter", n));
|
|
4182
4366
|
});
|
|
4183
4367
|
const u = document.createElement("div");
|
|
4184
|
-
u.className = "dtabbody",
|
|
4368
|
+
u.className = "dtabbody", p.forEach((v) => u.appendChild(v)), a.append(h, u), g(0), setTimeout(() => t.focus(), 0);
|
|
4185
4369
|
},
|
|
4186
4370
|
[
|
|
4187
4371
|
{ label: this.t("cancel"), action: () => this.closeDlg() },
|
|
@@ -4189,21 +4373,21 @@ const I = class I {
|
|
|
4189
4373
|
label: this.t("save"),
|
|
4190
4374
|
primary: !0,
|
|
4191
4375
|
action: () => {
|
|
4192
|
-
const
|
|
4193
|
-
if (this.closeDlg(), !
|
|
4194
|
-
if (this.restoreSel(),
|
|
4195
|
-
document.execCommand("insertHTML", !1, `<span class="video-embed" contenteditable="false">${
|
|
4376
|
+
const a = s.value.trim(), h = t.value.trim(), p = parseInt(e.value, 10) || 560, m = parseInt(i.value, 10) || 314;
|
|
4377
|
+
if (this.closeDlg(), !a && !h) return;
|
|
4378
|
+
if (this.restoreSel(), a) {
|
|
4379
|
+
document.execCommand("insertHTML", !1, `<span class="video-embed" contenteditable="false">${a}</span>`), this.onChange();
|
|
4196
4380
|
return;
|
|
4197
4381
|
}
|
|
4198
4382
|
const g = this.videoEmbedUrl(h);
|
|
4199
4383
|
if (g)
|
|
4200
|
-
document.execCommand("insertHTML", !1, this.videoEmbedHTML(g,
|
|
4384
|
+
document.execCommand("insertHTML", !1, this.videoEmbedHTML(g, p, m));
|
|
4201
4385
|
else {
|
|
4202
|
-
const u = l.value.trim(), v =
|
|
4386
|
+
const u = l.value.trim(), v = n.value.trim();
|
|
4203
4387
|
document.execCommand(
|
|
4204
4388
|
"insertHTML",
|
|
4205
4389
|
!1,
|
|
4206
|
-
`<video controls width="${
|
|
4390
|
+
`<video controls width="${p}" height="${m}"${v ? ` poster="${this.escapeAttr(v)}"` : ""}><source src="${this.escapeAttr(h)}">${u ? `<source src="${this.escapeAttr(u)}">` : ""}</video>`
|
|
4207
4391
|
);
|
|
4208
4392
|
}
|
|
4209
4393
|
this.onChange();
|
|
@@ -4261,15 +4445,15 @@ const I = class I {
|
|
|
4261
4445
|
if (i.nodeType !== Node.TEXT_NODE || !this.ed.contains(i) || (h = i.parentElement) != null && h.closest("code, pre")) return;
|
|
4262
4446
|
const l = (i.textContent || "").slice(0, e.anchorOffset).match(/(?:^|[^`])`([^`]+)$/);
|
|
4263
4447
|
if (!l) return;
|
|
4264
|
-
const
|
|
4265
|
-
if (/^\s|\s$/.test(
|
|
4448
|
+
const n = l[1];
|
|
4449
|
+
if (/^\s|\s$/.test(n)) return;
|
|
4266
4450
|
t.preventDefault();
|
|
4267
|
-
const
|
|
4268
|
-
|
|
4451
|
+
const o = document.createRange();
|
|
4452
|
+
o.setStart(i, e.anchorOffset - n.length - 1), o.setEnd(i, e.anchorOffset), o.deleteContents();
|
|
4269
4453
|
const r = document.createElement("code");
|
|
4270
|
-
r.textContent =
|
|
4271
|
-
const
|
|
4272
|
-
|
|
4454
|
+
r.textContent = n, o.insertNode(r);
|
|
4455
|
+
const a = document.createRange();
|
|
4456
|
+
a.setStartAfter(r), a.collapse(!0), e.removeAllRanges(), e.addRange(a), this.saveSel(), this.onChange();
|
|
4273
4457
|
}
|
|
4274
4458
|
/** Custom dropdown for dialog fields (a native <select> popup can't be styled):
|
|
4275
4459
|
* a field-styled button showing the current choice that opens a floating,
|
|
@@ -4281,22 +4465,22 @@ const I = class I {
|
|
|
4281
4465
|
s.className = "dsel";
|
|
4282
4466
|
const l = document.createElement("button");
|
|
4283
4467
|
l.type = "button", l.className = "dsel-btn";
|
|
4284
|
-
const
|
|
4285
|
-
|
|
4286
|
-
const
|
|
4287
|
-
return
|
|
4288
|
-
const
|
|
4289
|
-
|
|
4290
|
-
i =
|
|
4291
|
-
}),
|
|
4468
|
+
const n = document.createElement("span");
|
|
4469
|
+
n.className = "lbl", n.textContent = ((r = t.find(([a]) => a === e)) == null ? void 0 : r[1]) || "", l.append(n), l.insertAdjacentHTML("beforeend", c.chev);
|
|
4470
|
+
const o = document.createElement("div");
|
|
4471
|
+
return o.className = "dsel-list", t.forEach(([a, h]) => {
|
|
4472
|
+
const p = document.createElement("button");
|
|
4473
|
+
p.type = "button", p.textContent = h, p.classList.toggle("on", a === i), p.addEventListener("click", () => {
|
|
4474
|
+
i = a, n.textContent = h, o.querySelectorAll("button").forEach((m) => m.classList.toggle("on", m === p)), s.classList.remove("open"), l.focus();
|
|
4475
|
+
}), o.appendChild(p);
|
|
4292
4476
|
}), l.addEventListener("click", () => {
|
|
4293
|
-
var
|
|
4294
|
-
s.classList.toggle("open"), s.classList.contains("open") && ((
|
|
4295
|
-
}), s.addEventListener("focusout", (
|
|
4296
|
-
s.contains(
|
|
4297
|
-
}), s.addEventListener("keydown", (
|
|
4298
|
-
|
|
4299
|
-
}), s.append(l,
|
|
4477
|
+
var a;
|
|
4478
|
+
s.classList.toggle("open"), s.classList.contains("open") && ((a = o.querySelector(".on")) == null || a.scrollIntoView({ block: "nearest" }));
|
|
4479
|
+
}), s.addEventListener("focusout", (a) => {
|
|
4480
|
+
s.contains(a.relatedTarget) || s.classList.remove("open");
|
|
4481
|
+
}), s.addEventListener("keydown", (a) => {
|
|
4482
|
+
a.key === "Escape" && s.classList.contains("open") && (a.stopPropagation(), s.classList.remove("open"), l.focus());
|
|
4483
|
+
}), s.append(l, o), { el: s, value: () => i };
|
|
4300
4484
|
}
|
|
4301
4485
|
/** Insert/edit-code-sample dialog: language dropdown + monospace textarea to
|
|
4302
4486
|
* paste or type code into. Inserts a non-editable <pre class="code-block">
|
|
@@ -4307,11 +4491,11 @@ const I = class I {
|
|
|
4307
4491
|
this.dialog(
|
|
4308
4492
|
this.t("codedlgttl"),
|
|
4309
4493
|
(s) => {
|
|
4310
|
-
var
|
|
4494
|
+
var o;
|
|
4311
4495
|
const l = document.createElement("div");
|
|
4312
4496
|
l.className = "dfield";
|
|
4313
|
-
const
|
|
4314
|
-
|
|
4497
|
+
const n = document.createElement("label");
|
|
4498
|
+
n.textContent = this.t("codelang"), e = this.dlgSelect(V, (t == null ? void 0 : t.dataset.lang) || "plain"), l.append(n, e.el), i = document.createElement("textarea"), i.className = "code-input", i.spellcheck = !1, i.value = ((o = t == null ? void 0 : t.querySelector("code")) == null ? void 0 : o.textContent) || "", i.placeholder = "const answer = 42;", s.append(l, i), setTimeout(() => i.focus(), 0);
|
|
4315
4499
|
},
|
|
4316
4500
|
[
|
|
4317
4501
|
{ label: this.t("cancel"), action: () => this.closeDlg() },
|
|
@@ -4319,11 +4503,11 @@ const I = class I {
|
|
|
4319
4503
|
label: this.t("save"),
|
|
4320
4504
|
primary: !0,
|
|
4321
4505
|
action: () => {
|
|
4322
|
-
var
|
|
4323
|
-
const s = i.value.replace(/\s+$/, ""), l = e.value(),
|
|
4506
|
+
var o;
|
|
4507
|
+
const s = i.value.replace(/\s+$/, ""), l = e.value(), n = ((o = V.find(([r]) => r === l)) == null ? void 0 : o[1]) || l;
|
|
4324
4508
|
if (this.closeDlg(), !!s.trim()) {
|
|
4325
4509
|
if (t) {
|
|
4326
|
-
t.dataset.lang = l, t.setAttribute("data-lang-label",
|
|
4510
|
+
t.dataset.lang = l, t.setAttribute("data-lang-label", n);
|
|
4327
4511
|
const r = t.querySelector("code") || t;
|
|
4328
4512
|
r.textContent = s, this.clearCodeSel(), this.onChange();
|
|
4329
4513
|
return;
|
|
@@ -4331,7 +4515,7 @@ const I = class I {
|
|
|
4331
4515
|
this.restoreSel(), document.execCommand(
|
|
4332
4516
|
"insertHTML",
|
|
4333
4517
|
!1,
|
|
4334
|
-
`<pre class="code-block" contenteditable="false" data-lang="${l}" data-lang-label="${this.escapeAttr(
|
|
4518
|
+
`<pre class="code-block" contenteditable="false" data-lang="${l}" data-lang-label="${this.escapeAttr(n)}"><code>${this.escHtml(s)}</code></pre><p><br></p>`
|
|
4335
4519
|
), this.onChange();
|
|
4336
4520
|
}
|
|
4337
4521
|
}
|
|
@@ -4349,10 +4533,10 @@ const I = class I {
|
|
|
4349
4533
|
buildCodeCtxToolbar(t) {
|
|
4350
4534
|
const e = document.createElement("div");
|
|
4351
4535
|
return e.className = "imgctx", e.dir = this.dir(), e.append(
|
|
4352
|
-
this.ctxBtn(
|
|
4353
|
-
this.ctxBtn(
|
|
4536
|
+
this.ctxBtn(c.editic, this.t("editcode"), () => this.codeDlg(t)),
|
|
4537
|
+
this.ctxBtn(c.copyic, this.t("copycode"), () => this.copyCodeBlock(t)),
|
|
4354
4538
|
this.ctxSep(),
|
|
4355
|
-
this.ctxBtn(
|
|
4539
|
+
this.ctxBtn(c.trash, this.t("deletecode"), () => {
|
|
4356
4540
|
t.remove(), this.clearCodeSel(), this.onChange();
|
|
4357
4541
|
})
|
|
4358
4542
|
), e.addEventListener("mousedown", (i) => i.preventDefault()), document.body.appendChild(e), e;
|
|
@@ -4388,14 +4572,14 @@ const I = class I {
|
|
|
4388
4572
|
/** Miniature div-based mockup of a layout, mirroring what the block looks
|
|
4389
4573
|
like in the editor: grey box = image slot, bars = heading/paragraph. */
|
|
4390
4574
|
tplPreviewHTML(t) {
|
|
4391
|
-
const e = '<span class="pv-img"></span>', i = '<span class="pv-h"></span>', s = (r) => `<span class="pv-l" style="width:${r}%"></span>`, l = (r) => `<span class="pv-col">${r}</span>`,
|
|
4392
|
-
return t === "img-left" ? `<span class="pv">${
|
|
4575
|
+
const e = '<span class="pv-img"></span>', i = '<span class="pv-h"></span>', s = (r) => `<span class="pv-l" style="width:${r}%"></span>`, l = (r) => `<span class="pv-col">${r}</span>`, n = (r) => `<span class="pv-row">${r}</span>`, o = l(i + s(100) + s(88));
|
|
4576
|
+
return t === "img-left" ? `<span class="pv">${n(e + o)}${s(100)}${s(72)}</span>` : t === "img-right" ? `<span class="pv">${n(o + e)}${s(100)}${s(72)}</span>` : t === "img-top" ? `<span class="pv pv-c">${e}${i}${s(100)}${s(72)}</span>` : `<span class="pv pv-c">${i}${s(100)}${s(72)}${e}</span>`;
|
|
4393
4577
|
}
|
|
4394
4578
|
buildTemplatePickInto(t, e) {
|
|
4395
4579
|
const i = document.createElement("div");
|
|
4396
|
-
i.className = "tplpick",
|
|
4580
|
+
i.className = "tplpick", O.forEach((s) => {
|
|
4397
4581
|
const l = document.createElement("button");
|
|
4398
|
-
l.type = "button", l.className = "tpltile", l.title = this.t(
|
|
4582
|
+
l.type = "button", l.className = "tpltile", l.title = this.t($[s]), l.innerHTML = this.tplPreviewHTML(s) + `<span class="tpllbl">${this.t($[s])}</span>`, l.addEventListener("click", () => {
|
|
4399
4583
|
this.closePop(), this.insertTemplate(s), e == null || e();
|
|
4400
4584
|
}), i.appendChild(l);
|
|
4401
4585
|
}), t.appendChild(i);
|
|
@@ -4414,15 +4598,15 @@ const I = class I {
|
|
|
4414
4598
|
}
|
|
4415
4599
|
renderTplCtxButtons() {
|
|
4416
4600
|
const t = this.tplCtx, e = this.tplActive;
|
|
4417
|
-
!t || !e || (t.innerHTML = "",
|
|
4418
|
-
const s = this.ctxBtn(
|
|
4601
|
+
!t || !e || (t.innerHTML = "", O.forEach((i) => {
|
|
4602
|
+
const s = this.ctxBtn(Wt[i], this.t($[i]), () => this.setTplLayout(i));
|
|
4419
4603
|
s.classList.toggle("on", e.classList.contains("tpl-" + i)), t.appendChild(s);
|
|
4420
|
-
}), t.append(this.ctxSep(), this.ctxBtn(
|
|
4604
|
+
}), t.append(this.ctxSep(), this.ctxBtn(c.trash, this.t("deltemplate"), () => this.removeTemplate())), this.positionTplCtx());
|
|
4421
4605
|
}
|
|
4422
4606
|
setTplLayout(t) {
|
|
4423
4607
|
const e = this.tplActive;
|
|
4424
4608
|
if (!e) return;
|
|
4425
|
-
|
|
4609
|
+
O.forEach((l) => e.classList.remove("tpl-" + l)), e.classList.add("tpl-" + t);
|
|
4426
4610
|
const i = e.querySelector(":scope > .tpl-media"), s = e.querySelector(":scope > .tpl-text");
|
|
4427
4611
|
i && s && (t === "img-center" ? e.appendChild(i) : e.insertBefore(i, s)), this.renderTplCtxButtons(), this.positionImgPhCtx(), this.positionImageHandles(), this.onChange();
|
|
4428
4612
|
}
|
|
@@ -4454,7 +4638,7 @@ const I = class I {
|
|
|
4454
4638
|
/* ---------------------------------------------------------- table resize */
|
|
4455
4639
|
clearTableHandles() {
|
|
4456
4640
|
var t, e, i, s, l;
|
|
4457
|
-
(t = this.tblCorner) == null || t.remove(), this.tblCorner = null, this.tblColBars.forEach((
|
|
4641
|
+
(t = this.tblCorner) == null || t.remove(), this.tblCorner = null, this.tblColBars.forEach((n) => n.remove()), this.tblColBars = [], (e = this.tblCtx) == null || e.remove(), this.tblCtx = null, (i = this.tblCellMark) == null || i.remove(), this.tblCellMark = null, (s = this.tblOpMark) == null || s.remove(), this.tblOpMark = null, this.tblOpMarkKind = null, (l = this.tblActive) == null || l.classList.remove("tbl-selected"), this.tblActive = null;
|
|
4458
4642
|
}
|
|
4459
4643
|
/** Blue outline around the cell that holds the caret, so it is clear
|
|
4460
4644
|
which cell / row / column the table operations will target. */
|
|
@@ -4481,8 +4665,8 @@ const I = class I {
|
|
|
4481
4665
|
return;
|
|
4482
4666
|
}
|
|
4483
4667
|
this.tblOpMark || (this.tblOpMark = document.createElement("div"), this.tblOpMark.className = "tbl-opmark", document.body.appendChild(this.tblOpMark));
|
|
4484
|
-
const i = this.tblActive.getBoundingClientRect(), s = e.getBoundingClientRect(), l = e.parentElement.getBoundingClientRect(),
|
|
4485
|
-
this.tblOpMark.style.left =
|
|
4668
|
+
const i = this.tblActive.getBoundingClientRect(), s = e.getBoundingClientRect(), l = e.parentElement.getBoundingClientRect(), n = t === "row" ? l.left : s.left, o = t === "row" ? l.top : i.top, r = t === "row" ? l.width : s.width, a = t === "row" ? l.height : i.height;
|
|
4669
|
+
this.tblOpMark.style.left = n + scrollX + "px", this.tblOpMark.style.top = o + scrollY + "px", this.tblOpMark.style.width = r + "px", this.tblOpMark.style.height = a + "px";
|
|
4486
4670
|
}
|
|
4487
4671
|
/** Lowest allowed top for floating context toolbars — keeps them from
|
|
4488
4672
|
covering the editor menubar/toolbar when the target sits on the first line. */
|
|
@@ -4491,7 +4675,7 @@ const I = class I {
|
|
|
4491
4675
|
}
|
|
4492
4676
|
ctxBtn(t, e, i, s) {
|
|
4493
4677
|
const l = document.createElement("button");
|
|
4494
|
-
return l.type = "button", l.title = e, l.innerHTML = t, s && (l.dataset.id = s), l.addEventListener("mousedown", (
|
|
4678
|
+
return l.type = "button", l.title = e, l.innerHTML = t, s && (l.dataset.id = s), l.addEventListener("mousedown", (n) => n.preventDefault()), l.addEventListener("click", i), l;
|
|
4495
4679
|
}
|
|
4496
4680
|
ctxSep() {
|
|
4497
4681
|
const t = document.createElement("div");
|
|
@@ -4500,27 +4684,27 @@ const I = class I {
|
|
|
4500
4684
|
buildTableCtxToolbar() {
|
|
4501
4685
|
const t = document.createElement("div");
|
|
4502
4686
|
t.className = "tblctx", t.dir = this.dir();
|
|
4503
|
-
const e = (s, l) => (s.addEventListener("mouseenter", () => this.setOpTarget(l)), s.addEventListener("mouseleave", () => this.setOpTarget(null)), s), i = this.ctxBtn(
|
|
4687
|
+
const e = (s, l) => (s.addEventListener("mouseenter", () => this.setOpTarget(l)), s.addEventListener("mouseleave", () => this.setOpTarget(null)), s), i = this.ctxBtn(c.palette, this.t("cellbg"), () => this.cellFillMenu(i));
|
|
4504
4688
|
return t.append(
|
|
4505
|
-
e(this.ctxBtn(
|
|
4506
|
-
e(this.ctxBtn(
|
|
4507
|
-
e(this.ctxBtn(
|
|
4508
|
-
e(this.ctxBtn(
|
|
4509
|
-
e(this.ctxBtn(
|
|
4689
|
+
e(this.ctxBtn(c.rowbefore, this.t("rowabove"), () => this.tableOp("rowabove")), "row"),
|
|
4690
|
+
e(this.ctxBtn(c.rowafter, this.t("rowbelow"), () => this.tableOp("rowbelow")), "row"),
|
|
4691
|
+
e(this.ctxBtn(c.moverowup, this.t("moverowup"), () => this.tableMove("rowup")), "row"),
|
|
4692
|
+
e(this.ctxBtn(c.moverowdown, this.t("moverowdown"), () => this.tableMove("rowdown")), "row"),
|
|
4693
|
+
e(this.ctxBtn(c.rowdelete, this.t("delrow"), () => this.tableOp("delrow")), "row"),
|
|
4510
4694
|
this.ctxSep(),
|
|
4511
|
-
e(this.ctxBtn(
|
|
4512
|
-
e(this.ctxBtn(
|
|
4513
|
-
e(this.ctxBtn(
|
|
4514
|
-
e(this.ctxBtn(
|
|
4515
|
-
e(this.ctxBtn(
|
|
4695
|
+
e(this.ctxBtn(c.colbefore, this.t("colbefore"), () => this.tableOp("colbefore")), "col"),
|
|
4696
|
+
e(this.ctxBtn(c.colafter, this.t("colafter"), () => this.tableOp("colafter")), "col"),
|
|
4697
|
+
e(this.ctxBtn(c.movecolleft, this.t("movecolleft"), () => this.tableMove("colleft")), "col"),
|
|
4698
|
+
e(this.ctxBtn(c.movecolright, this.t("movecolright"), () => this.tableMove("colright")), "col"),
|
|
4699
|
+
e(this.ctxBtn(c.coldelete, this.t("delcol"), () => this.tableOp("delcol")), "col"),
|
|
4516
4700
|
this.ctxSep(),
|
|
4517
|
-
this.ctxBtn(
|
|
4518
|
-
this.ctxBtn(
|
|
4519
|
-
this.ctxBtn(
|
|
4701
|
+
this.ctxBtn(c.alignleft, this.t("tblalignleft"), () => this.alignTable("left")),
|
|
4702
|
+
this.ctxBtn(c.aligncenter, this.t("tblaligncenter"), () => this.alignTable("center")),
|
|
4703
|
+
this.ctxBtn(c.alignright, this.t("tblalignright"), () => this.alignTable("right")),
|
|
4520
4704
|
this.ctxSep(),
|
|
4521
4705
|
i,
|
|
4522
|
-
this.ctxBtn(
|
|
4523
|
-
this.ctxBtn(
|
|
4706
|
+
this.ctxBtn(c.trash, this.t("deltable"), () => this.tableOp("deltable")),
|
|
4707
|
+
this.ctxBtn(c.tableic, this.t("tablepropsttl"), () => this.tablePropsDlg())
|
|
4524
4708
|
), document.body.appendChild(t), t;
|
|
4525
4709
|
}
|
|
4526
4710
|
positionTableHandles() {
|
|
@@ -4528,20 +4712,20 @@ const I = class I {
|
|
|
4528
4712
|
this.clearTableHandles();
|
|
4529
4713
|
return;
|
|
4530
4714
|
}
|
|
4531
|
-
const t = this.ed.getAttribute("dir") === "rtl", e = this.tblActive.getBoundingClientRect(), i = e.top + scrollY, s = e.left + scrollX, l = e.right + scrollX,
|
|
4532
|
-
if (this.tblCorner && (this.tblCorner.style.top =
|
|
4533
|
-
const r = this.tblCtx.offsetWidth,
|
|
4715
|
+
const t = this.ed.getAttribute("dir") === "rtl", e = this.tblActive.getBoundingClientRect(), i = e.top + scrollY, s = e.left + scrollX, l = e.right + scrollX, n = e.bottom + scrollY;
|
|
4716
|
+
if (this.tblCorner && (this.tblCorner.style.top = n - 5 + "px", this.tblCorner.style.left = (t ? s - 5 : l - 5) + "px", this.tblCorner.style.cursor = t ? "nesw-resize" : "nwse-resize"), this.tblCtx) {
|
|
4717
|
+
const r = this.tblCtx.offsetWidth, a = this.tblCtx.offsetHeight;
|
|
4534
4718
|
let h = s + (l - s) / 2 - r / 2;
|
|
4535
4719
|
h = Math.max(8 + scrollX, Math.min(h, scrollX + innerWidth - r - 8));
|
|
4536
|
-
let
|
|
4537
|
-
|
|
4720
|
+
let p = i - a - 8;
|
|
4721
|
+
p < this.ctxMinTop() && (p = n + 8), this.tblCtx.style.left = h + "px", this.tblCtx.style.top = p + "px";
|
|
4538
4722
|
}
|
|
4539
4723
|
this.tblColBars.forEach((r) => r.remove()), this.tblColBars = [];
|
|
4540
|
-
const
|
|
4541
|
-
if (
|
|
4542
|
-
for (let r = 0; r <
|
|
4543
|
-
const
|
|
4544
|
-
|
|
4724
|
+
const o = this.tblActive.rows[0];
|
|
4725
|
+
if (o)
|
|
4726
|
+
for (let r = 0; r < o.cells.length - 1; r++) {
|
|
4727
|
+
const a = o.cells[r].getBoundingClientRect(), h = (t ? a.left : a.right) + scrollX, p = document.createElement("div");
|
|
4728
|
+
p.className = "tbl-colbar", p.style.top = i + "px", p.style.left = h + "px", p.style.height = n - i + "px", document.body.appendChild(p), p.addEventListener("mousedown", (m) => this.startColBarDrag(m, r)), this.tblColBars.push(p);
|
|
4545
4729
|
}
|
|
4546
4730
|
this.positionCellMarker(), this.positionOpMark();
|
|
4547
4731
|
}
|
|
@@ -4559,29 +4743,29 @@ const I = class I {
|
|
|
4559
4743
|
const e = this.tblActive;
|
|
4560
4744
|
if (!e) return;
|
|
4561
4745
|
const i = this.ed.getAttribute("dir") === "rtl", s = t.clientX, l = e.getBoundingClientRect().width;
|
|
4562
|
-
e.style.tableLayout = e.style.tableLayout || "fixed", this.withNoTextSelect((
|
|
4563
|
-
const
|
|
4564
|
-
const h = i ? -(
|
|
4746
|
+
e.style.tableLayout = e.style.tableLayout || "fixed", this.withNoTextSelect((n) => {
|
|
4747
|
+
const o = (a) => {
|
|
4748
|
+
const h = i ? -(a.clientX - s) : a.clientX - s;
|
|
4565
4749
|
e.style.width = Math.max(60, Math.round(l + h)) + "px", this.positionTableHandles();
|
|
4566
4750
|
}, r = () => {
|
|
4567
|
-
window.removeEventListener("mousemove",
|
|
4751
|
+
window.removeEventListener("mousemove", o), window.removeEventListener("mouseup", r), n(), this.onChange();
|
|
4568
4752
|
};
|
|
4569
|
-
window.addEventListener("mousemove",
|
|
4753
|
+
window.addEventListener("mousemove", o), window.addEventListener("mouseup", r);
|
|
4570
4754
|
});
|
|
4571
4755
|
}
|
|
4572
4756
|
startColBarDrag(t, e) {
|
|
4573
4757
|
t.preventDefault(), t.stopPropagation();
|
|
4574
4758
|
const i = this.tblActive;
|
|
4575
4759
|
if (!i) return;
|
|
4576
|
-
const s = this.ed.getAttribute("dir") === "rtl", l = Array.from(i.rows),
|
|
4577
|
-
if (!
|
|
4578
|
-
const r = t.clientX,
|
|
4579
|
-
i.style.tableLayout = "fixed", this.withNoTextSelect((
|
|
4760
|
+
const s = this.ed.getAttribute("dir") === "rtl", l = Array.from(i.rows), n = l.map((p) => p.cells[e]).filter(Boolean), o = l.map((p) => p.cells[e + 1]).filter(Boolean);
|
|
4761
|
+
if (!n.length || !o.length) return;
|
|
4762
|
+
const r = t.clientX, a = n[0].getBoundingClientRect().width, h = o[0].getBoundingClientRect().width;
|
|
4763
|
+
i.style.tableLayout = "fixed", this.withNoTextSelect((p) => {
|
|
4580
4764
|
const m = (u) => {
|
|
4581
4765
|
const v = (s ? -1 : 1) * (u.clientX - r);
|
|
4582
|
-
|
|
4766
|
+
n.forEach((b) => b.style.width = Math.max(24, Math.round(a + v)) + "px"), o.forEach((b) => b.style.width = Math.max(24, Math.round(h - v)) + "px"), this.positionTableHandles();
|
|
4583
4767
|
}, g = () => {
|
|
4584
|
-
window.removeEventListener("mousemove", m), window.removeEventListener("mouseup", g),
|
|
4768
|
+
window.removeEventListener("mousemove", m), window.removeEventListener("mouseup", g), p(), this.onChange();
|
|
4585
4769
|
};
|
|
4586
4770
|
window.addEventListener("mousemove", m), window.addEventListener("mouseup", g);
|
|
4587
4771
|
});
|
|
@@ -4598,7 +4782,7 @@ const I = class I {
|
|
|
4598
4782
|
this.cancelImgHide(), this.imgHandles.forEach((i) => i.remove()), this.imgHandles = [], (t = this.imgCtx) == null || t.remove(), this.imgCtx = null, (e = this.imgActive) == null || e.classList.remove("img-selected"), this.imgActive = null;
|
|
4599
4783
|
}
|
|
4600
4784
|
selectImage(t) {
|
|
4601
|
-
this.imgActive !== t && (this.clearImageHandles(), this.imgActive = t, t.classList.add("img-selected"), this.imgHandles =
|
|
4785
|
+
this.imgActive !== t && (this.clearImageHandles(), this.imgActive = t, t.classList.add("img-selected"), this.imgHandles = Ut.map((e) => {
|
|
4602
4786
|
const i = document.createElement("div");
|
|
4603
4787
|
return i.className = "img-handle img-handle-" + e, i.dataset.corner = e, i.addEventListener("mousedown", (s) => this.startImageResizeDrag(s, e)), i.addEventListener("mouseenter", () => this.cancelImgHide()), i.addEventListener("mouseleave", () => this.scheduleImgHide()), document.body.appendChild(i), i;
|
|
4604
4788
|
}), this.imgCtx = this.buildImageCtxToolbar(t), this.positionImageHandles());
|
|
@@ -4608,38 +4792,38 @@ const I = class I {
|
|
|
4608
4792
|
e.className = "imgctx", e.dir = this.dir();
|
|
4609
4793
|
const i = () => {
|
|
4610
4794
|
var h;
|
|
4611
|
-
const
|
|
4612
|
-
(h = this.imgCtx) == null || h.replaceWith(
|
|
4613
|
-
}, s = (
|
|
4614
|
-
this.setImageAlign(t,
|
|
4615
|
-
}, l = t.style.float === "left",
|
|
4616
|
-
const g = this.ctxBtn(
|
|
4617
|
-
return g.classList.toggle("on",
|
|
4795
|
+
const a = this.buildImageCtxToolbar(t);
|
|
4796
|
+
(h = this.imgCtx) == null || h.replaceWith(a), this.imgCtx = a, this.positionImageHandles();
|
|
4797
|
+
}, s = (a) => {
|
|
4798
|
+
this.setImageAlign(t, a), i();
|
|
4799
|
+
}, l = t.style.float === "left", n = t.style.float === "right", o = !l && !n && t.style.marginLeft === "auto" && t.style.marginRight === "auto", r = (a, h, p, m) => {
|
|
4800
|
+
const g = this.ctxBtn(a, h, m);
|
|
4801
|
+
return g.classList.toggle("on", p), g;
|
|
4618
4802
|
};
|
|
4619
4803
|
return e.append(
|
|
4620
|
-
r(
|
|
4621
|
-
r(
|
|
4622
|
-
r(
|
|
4804
|
+
r(c.alignleft, this.t("alignleft"), l, () => s("left")),
|
|
4805
|
+
r(c.aligncenter, this.t("aligncenter"), o, () => s("center")),
|
|
4806
|
+
r(c.alignright, this.t("alignright"), n, () => s("right")),
|
|
4623
4807
|
this.ctxSep(),
|
|
4624
|
-
r(
|
|
4808
|
+
r(c.rotateleft, this.t("rotateleft"), !1, () => {
|
|
4625
4809
|
this.rotateImage(t, -90), i();
|
|
4626
4810
|
}),
|
|
4627
|
-
r(
|
|
4811
|
+
r(c.rotateright, this.t("rotateright"), !1, () => {
|
|
4628
4812
|
this.rotateImage(t, 90), i();
|
|
4629
4813
|
}),
|
|
4630
4814
|
this.ctxSep(),
|
|
4631
|
-
r(
|
|
4815
|
+
r(c.fliphorizontal, this.t("fliphorizontal"), t.dataset.flipx === "1", () => {
|
|
4632
4816
|
this.flipImage(t, "x"), i();
|
|
4633
4817
|
}),
|
|
4634
|
-
r(
|
|
4818
|
+
r(c.flipvertical, this.t("flipvertical"), t.dataset.flipy === "1", () => {
|
|
4635
4819
|
this.flipImage(t, "y"), i();
|
|
4636
4820
|
}),
|
|
4637
4821
|
this.ctxSep(),
|
|
4638
|
-
r(
|
|
4639
|
-
const
|
|
4640
|
-
|
|
4822
|
+
r(c.trash, this.t("deleteimg"), !1, () => {
|
|
4823
|
+
const a = t.closest(".tpl-media");
|
|
4824
|
+
a && this.ed.contains(a) ? t.outerHTML = this.imgPhHTML() : t.remove(), this.clearImageHandles(), this.onChange();
|
|
4641
4825
|
})
|
|
4642
|
-
), e.addEventListener("mousedown", (
|
|
4826
|
+
), e.addEventListener("mousedown", (a) => a.preventDefault()), e.addEventListener("mouseenter", () => this.cancelImgHide()), e.addEventListener("mouseleave", () => this.scheduleImgHide()), document.body.appendChild(e), e;
|
|
4643
4827
|
}
|
|
4644
4828
|
setImageAlign(t, e) {
|
|
4645
4829
|
t.style.float = "", t.style.display = "", t.style.marginLeft = "", t.style.marginRight = "", t.style.marginBottom = "", e === "left" ? (t.style.float = "left", t.style.marginInlineEnd = "1em", t.style.marginBottom = "0.5em") : e === "right" ? (t.style.float = "right", t.style.marginInlineStart = "1em", t.style.marginBottom = "0.5em") : (t.style.display = "block", t.style.marginLeft = "auto", t.style.marginRight = "auto"), this.onChange();
|
|
@@ -4661,21 +4845,21 @@ const I = class I {
|
|
|
4661
4845
|
this.clearImageHandles();
|
|
4662
4846
|
return;
|
|
4663
4847
|
}
|
|
4664
|
-
const t = this.imgActive.getBoundingClientRect(), e = t.top + scrollY, i = t.left + scrollX, s = t.right + scrollX, l = t.bottom + scrollY,
|
|
4848
|
+
const t = this.imgActive.getBoundingClientRect(), e = t.top + scrollY, i = t.left + scrollX, s = t.right + scrollX, l = t.bottom + scrollY, n = {
|
|
4665
4849
|
nw: [i, e],
|
|
4666
4850
|
ne: [s, e],
|
|
4667
4851
|
sw: [i, l],
|
|
4668
4852
|
se: [s, l]
|
|
4669
4853
|
};
|
|
4670
|
-
if (this.imgHandles.forEach((
|
|
4671
|
-
const [r,
|
|
4672
|
-
|
|
4854
|
+
if (this.imgHandles.forEach((o) => {
|
|
4855
|
+
const [r, a] = n[o.dataset.corner];
|
|
4856
|
+
o.style.left = r - 5 + "px", o.style.top = a - 5 + "px";
|
|
4673
4857
|
}), this.imgCtx) {
|
|
4674
|
-
const
|
|
4675
|
-
let
|
|
4676
|
-
|
|
4858
|
+
const o = this.imgCtx.offsetWidth, r = this.imgCtx.offsetHeight;
|
|
4859
|
+
let a = i + (s - i) / 2 - o / 2;
|
|
4860
|
+
a = Math.max(8 + scrollX, Math.min(a, scrollX + innerWidth - o - 8));
|
|
4677
4861
|
let h = e - r - 8;
|
|
4678
|
-
h < this.ctxMinTop() && (h = l + 8), this.imgCtx.style.left =
|
|
4862
|
+
h < this.ctxMinTop() && (h = l + 8), this.imgCtx.style.left = a + "px", this.imgCtx.style.top = h + "px";
|
|
4679
4863
|
}
|
|
4680
4864
|
}
|
|
4681
4865
|
startImageResizeDrag(t, e) {
|
|
@@ -4683,14 +4867,16 @@ const I = class I {
|
|
|
4683
4867
|
const i = this.imgActive;
|
|
4684
4868
|
if (!i) return;
|
|
4685
4869
|
this.cancelImgHide();
|
|
4686
|
-
const s = t.clientX, l = i.getBoundingClientRect().width,
|
|
4687
|
-
this.withNoTextSelect((
|
|
4870
|
+
const s = t.clientX, l = i.getBoundingClientRect().width, n = e === "nw" || e === "sw" ? -1 : 1;
|
|
4871
|
+
this.withNoTextSelect((o) => {
|
|
4688
4872
|
const r = (h) => {
|
|
4689
|
-
i.style.width = Math.max(24, Math.round(l +
|
|
4690
|
-
},
|
|
4691
|
-
window.removeEventListener("mousemove", r), window.removeEventListener("mouseup",
|
|
4873
|
+
i.style.width = Math.max(24, Math.round(l + n * (h.clientX - s))) + "px", i.style.height = "auto", this.positionImageHandles();
|
|
4874
|
+
}, a = () => {
|
|
4875
|
+
window.removeEventListener("mousemove", r), window.removeEventListener("mouseup", a), o();
|
|
4876
|
+
const h = parseInt(i.style.width, 10);
|
|
4877
|
+
h > 0 && !i.closest(".tpl-media") && (i.setAttribute("width", String(h)), i.removeAttribute("height")), this.onChange();
|
|
4692
4878
|
};
|
|
4693
|
-
window.addEventListener("mousemove", r), window.addEventListener("mouseup",
|
|
4879
|
+
window.addEventListener("mousemove", r), window.addEventListener("mouseup", a);
|
|
4694
4880
|
});
|
|
4695
4881
|
}
|
|
4696
4882
|
/* ---------------------------------------------------------- selection bubble toolbar */
|
|
@@ -4729,40 +4915,40 @@ const I = class I {
|
|
|
4729
4915
|
this.selCtx || (this.selCtx = this.buildSelToolbar()), this.positionSelToolbar(e);
|
|
4730
4916
|
}
|
|
4731
4917
|
buildSelToolbar() {
|
|
4732
|
-
var
|
|
4918
|
+
var o;
|
|
4733
4919
|
const t = document.createElement("div");
|
|
4734
4920
|
t.className = "selctx", t.dir = this.dir();
|
|
4735
4921
|
const e = this.ctxBtn(
|
|
4736
4922
|
'<b style="font:600 15px/1 Georgia,serif">A</b><span class="colorbar" data-cb="fore"></span>',
|
|
4737
4923
|
this.t("forecolor"),
|
|
4738
4924
|
() => this.colorMenu(e, "fore")
|
|
4739
|
-
), i = this.ctxBtn(
|
|
4740
|
-
(
|
|
4741
|
-
const s = this.ctxBtn(
|
|
4925
|
+
), i = this.ctxBtn(c.backcolor, this.t("backcolor"), () => this.colorMenu(i, "back"));
|
|
4926
|
+
(o = i.querySelector("svg")) == null || o.insertAdjacentHTML("afterend", '<span class="colorbar" data-cb="back"></span>');
|
|
4927
|
+
const s = this.ctxBtn(c.caseic, this.t("changecase"), () => this.caseMenu(s)), l = this.ctxBtn(c.lineheight, this.t("lineheight"), () => this.lineHeightMenu(l)), n = this.ctxBtn(c.wordspacing, this.t("wordspacing"), () => this.wordSpacingMenu(n));
|
|
4742
4928
|
return t.append(
|
|
4743
|
-
this.ctxBtn(
|
|
4744
|
-
this.ctxBtn(
|
|
4929
|
+
this.ctxBtn(c.bold, this.t("bold"), () => this.exec("bold"), "bold"),
|
|
4930
|
+
this.ctxBtn(c.italic, this.t("italic"), () => this.exec("italic"), "italic"),
|
|
4745
4931
|
e,
|
|
4746
4932
|
i,
|
|
4747
4933
|
this.ctxSep(),
|
|
4748
|
-
this.ctxBtn(
|
|
4749
|
-
this.ctxBtn(
|
|
4934
|
+
this.ctxBtn(c.quote, this.t("quote"), () => this.toggleBlock("blockquote"), "blockquote"),
|
|
4935
|
+
this.ctxBtn(c.inlinecodeic, this.t("code"), () => this.toggleInlineCode(), "code"),
|
|
4750
4936
|
this.ctxBtn('<b style="font:700 12px/1 Arial,sans-serif">H2</b>', this.blockLabel("h2"), () => this.toggleBlock("h2"), "h2"),
|
|
4751
4937
|
this.ctxBtn('<b style="font:700 12px/1 Arial,sans-serif">H3</b>', this.blockLabel("h3"), () => this.toggleBlock("h3"), "h3"),
|
|
4752
4938
|
this.ctxSep(),
|
|
4753
|
-
this.ctxBtn(
|
|
4939
|
+
this.ctxBtn(c.link, this.t("linkttl"), () => this.linkDlg()),
|
|
4754
4940
|
s,
|
|
4755
4941
|
l,
|
|
4756
|
-
|
|
4942
|
+
n
|
|
4757
4943
|
), t.addEventListener("mousedown", (r) => r.preventDefault()), document.body.appendChild(t), this.syncColorSwatches(t), t;
|
|
4758
4944
|
}
|
|
4759
4945
|
positionSelToolbar(t) {
|
|
4760
4946
|
if (!this.selCtx) return;
|
|
4761
|
-
const e = t.getBoundingClientRect(), i = e.top + scrollY, s = e.left + scrollX, l = e.right + scrollX,
|
|
4762
|
-
let
|
|
4763
|
-
|
|
4947
|
+
const e = t.getBoundingClientRect(), i = e.top + scrollY, s = e.left + scrollX, l = e.right + scrollX, n = e.bottom + scrollY, o = this.selCtx.offsetWidth, r = this.selCtx.offsetHeight;
|
|
4948
|
+
let a = s + (l - s) / 2 - o / 2;
|
|
4949
|
+
a = Math.max(8 + scrollX, Math.min(a, scrollX + innerWidth - o - 8));
|
|
4764
4950
|
let h = i - r - 8;
|
|
4765
|
-
h < this.ctxMinTop() && (h =
|
|
4951
|
+
h < this.ctxMinTop() && (h = n + 8), this.selCtx.style.left = a + "px", this.selCtx.style.top = h + "px";
|
|
4766
4952
|
}
|
|
4767
4953
|
repositionSelToolbar() {
|
|
4768
4954
|
if (!this.selCtx) return;
|
|
@@ -4795,9 +4981,9 @@ const I = class I {
|
|
|
4795
4981
|
return t > 0 ? t + "px" : "";
|
|
4796
4982
|
}
|
|
4797
4983
|
refreshState() {
|
|
4798
|
-
var r,
|
|
4984
|
+
var r, a, h;
|
|
4799
4985
|
const t = window.getSelection(), e = t ? this.ed.contains(t.anchorNode) : !1, i = this.currentBlock();
|
|
4800
|
-
[this.toolbar, this.selCtx].filter(Boolean).forEach((
|
|
4986
|
+
[this.toolbar, this.selCtx].filter(Boolean).forEach((p) => {
|
|
4801
4987
|
[
|
|
4802
4988
|
"bold",
|
|
4803
4989
|
"italic",
|
|
@@ -4810,22 +4996,22 @@ const I = class I {
|
|
|
4810
4996
|
"insertOrderedList",
|
|
4811
4997
|
"insertUnorderedList"
|
|
4812
4998
|
].forEach((g) => {
|
|
4813
|
-
const u =
|
|
4999
|
+
const u = p.querySelector(`[data-id=${g}]`);
|
|
4814
5000
|
u && u.classList.toggle("on", e && document.queryCommandState(g));
|
|
4815
5001
|
}), ["h2", "h3", "blockquote"].forEach((g) => {
|
|
4816
|
-
const u =
|
|
5002
|
+
const u = p.querySelector(`[data-id=${g}]`);
|
|
4817
5003
|
u && u.classList.toggle("on", e && i === g);
|
|
4818
5004
|
});
|
|
4819
|
-
const m =
|
|
5005
|
+
const m = p.querySelector("[data-id=code]");
|
|
4820
5006
|
m && m.classList.toggle("on", e && !!this.closestInlineCode());
|
|
4821
5007
|
});
|
|
4822
|
-
const l = t ? this.closestBlock(t.anchorNode) : null,
|
|
4823
|
-
(
|
|
4824
|
-
const
|
|
4825
|
-
const u = this.toolbar.querySelector(`[data-id=${
|
|
5008
|
+
const l = t ? this.closestBlock(t.anchorNode) : null, n = ((r = l == null ? void 0 : l.closest("[dir]")) == null ? void 0 : r.getAttribute("dir")) || this.ed.getAttribute("dir") || this.dir();
|
|
5009
|
+
(a = this.toolbar.querySelector("[data-id=ltr]")) == null || a.classList.toggle("on", e && n === "ltr"), (h = this.toolbar.querySelector("[data-id=rtl]")) == null || h.classList.toggle("on", e && n === "rtl");
|
|
5010
|
+
const o = (p, m, g) => {
|
|
5011
|
+
const u = this.toolbar.querySelector(`[data-id=${p}] .lbl`);
|
|
4826
5012
|
u && (u.textContent = m || g || "", u.classList.toggle("empty", !m));
|
|
4827
5013
|
};
|
|
4828
|
-
|
|
5014
|
+
o("fontsel", this.currentFont()), o("sizesel", this.currentSize().replace("px", "")), e && o("blocksel", X.some((p) => p[0] === i) ? this.blockLabel(i) : this.t("para")), this.sbWords.textContent = this.countWords() + " " + this.t("words");
|
|
4829
5015
|
}
|
|
4830
5016
|
countWords() {
|
|
4831
5017
|
const t = (this.ed.textContent || "").trim();
|
|
@@ -4840,18 +5026,75 @@ const I = class I {
|
|
|
4840
5026
|
if (s && !i) {
|
|
4841
5027
|
const l = new FileReader();
|
|
4842
5028
|
l.onload = () => {
|
|
4843
|
-
|
|
5029
|
+
this.insertImageHTML(l.result), this.onChange();
|
|
4844
5030
|
}, l.readAsDataURL(s.getAsFile());
|
|
4845
5031
|
return;
|
|
4846
5032
|
}
|
|
4847
5033
|
if (!i) {
|
|
4848
|
-
const l = e.getData("text/plain"),
|
|
4849
|
-
if (
|
|
4850
|
-
document.execCommand("insertHTML", !1, this.videoEmbedHTML(
|
|
5034
|
+
const l = e.getData("text/plain"), n = /^\S+$/.test(l.trim()) ? this.videoEmbedUrl(l.trim()) : null;
|
|
5035
|
+
if (n) {
|
|
5036
|
+
document.execCommand("insertHTML", !1, this.videoEmbedHTML(n)), this.onChange();
|
|
5037
|
+
return;
|
|
5038
|
+
}
|
|
5039
|
+
}
|
|
5040
|
+
i ? this.pasteRichHTML(i, e, s) : (document.execCommand("insertHTML", !1, kt(e.getData("text/plain"))), this.onChange());
|
|
5041
|
+
}
|
|
5042
|
+
/** Rich-HTML paste. Before the (untouched) paste engine runs, pictures Word left
|
|
5043
|
+
* behind as unreadable file:// refs are pulled out of the clipboard's RTF flavor
|
|
5044
|
+
* and inlined — the same pairing TinyMCE PowerPaste does for
|
|
5045
|
+
* powerpaste_allow_local_images. Everything the engine already handled is
|
|
5046
|
+
* unaffected: with no RTF, or no recoverable picture, the HTML reaches it
|
|
5047
|
+
* byte-identical to before. */
|
|
5048
|
+
pasteRichHTML(t, e, i) {
|
|
5049
|
+
let s = [];
|
|
5050
|
+
const l = e.getData("text/rtf");
|
|
5051
|
+
if (l) {
|
|
5052
|
+
const n = Pt(t, l);
|
|
5053
|
+
t = n.html, s = n.injected;
|
|
5054
|
+
}
|
|
5055
|
+
if (i && Rt(t) === 1) {
|
|
5056
|
+
const n = i.getAsFile();
|
|
5057
|
+
if (n) {
|
|
5058
|
+
const o = t;
|
|
5059
|
+
this.saveSel();
|
|
5060
|
+
const r = new FileReader();
|
|
5061
|
+
r.onload = () => {
|
|
5062
|
+
const a = nt(o, [r.result]);
|
|
5063
|
+
this.finishRichPaste(a.html, s.concat(a.injected), !0);
|
|
5064
|
+
}, r.onerror = () => this.finishRichPaste(o, s, !0), r.readAsDataURL(n);
|
|
4851
5065
|
return;
|
|
4852
5066
|
}
|
|
4853
5067
|
}
|
|
4854
|
-
|
|
5068
|
+
this.finishRichPaste(t, s);
|
|
5069
|
+
}
|
|
5070
|
+
/** Hands recovered pictures to the host's imageUploadHandler when one is
|
|
5071
|
+
* configured (PowerPaste's automatic_uploads equivalent), then inserts. Without a
|
|
5072
|
+
* handler they stay inline base64, which is what PowerPaste does by default. */
|
|
5073
|
+
finishRichPaste(t, e, i = !1) {
|
|
5074
|
+
if (!this.imageUploadHandler || !e.length) {
|
|
5075
|
+
this.insertPastedHTML(t, i);
|
|
5076
|
+
return;
|
|
5077
|
+
}
|
|
5078
|
+
const s = this.imageUploadHandler, l = e.filter((n, o) => e.indexOf(n) === o);
|
|
5079
|
+
i || this.saveSel(), Promise.all(
|
|
5080
|
+
l.map((n, o) => {
|
|
5081
|
+
const r = Dt(n, "pasted-image-" + (o + 1));
|
|
5082
|
+
return r ? s(r).catch((a) => {
|
|
5083
|
+
var h;
|
|
5084
|
+
return (h = this.onImageUploadError) == null || h.call(this, a, r), n;
|
|
5085
|
+
}) : Promise.resolve(n);
|
|
5086
|
+
})
|
|
5087
|
+
).then((n) => {
|
|
5088
|
+
let o = t;
|
|
5089
|
+
l.forEach((r, a) => {
|
|
5090
|
+
n[a] !== r && (o = o.split(r).join(n[a]));
|
|
5091
|
+
}), this.insertPastedHTML(o, !0);
|
|
5092
|
+
});
|
|
5093
|
+
}
|
|
5094
|
+
/** `deferred` means the insert is happening after an async hop, so the caret the
|
|
5095
|
+
* paste started from has to be put back first. */
|
|
5096
|
+
insertPastedHTML(t, e = !1) {
|
|
5097
|
+
e && this.restoreSel(), document.execCommand("insertHTML", !1, Ht(t, this.dir())), e && this.saveSel(), this.onChange();
|
|
4855
5098
|
}
|
|
4856
5099
|
/* ---------------------------------------------------------- init */
|
|
4857
5100
|
initUI() {
|
|
@@ -4859,18 +5102,18 @@ const I = class I {
|
|
|
4859
5102
|
}
|
|
4860
5103
|
};
|
|
4861
5104
|
I.instanceCounter = 0, I.TBR_COLLAPSE_MAX = 992;
|
|
4862
|
-
let
|
|
5105
|
+
let it = I;
|
|
4863
5106
|
export {
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
5107
|
+
X as BLOCKS,
|
|
5108
|
+
Jt as CHARS,
|
|
5109
|
+
gt as COLORS,
|
|
5110
|
+
ht as FONTS,
|
|
5111
|
+
it as FableEditor,
|
|
5112
|
+
rt as I18N,
|
|
5113
|
+
c as IC,
|
|
5114
|
+
dt as SIZES,
|
|
5115
|
+
te as TXT,
|
|
5116
|
+
Ht as cleanPastedHTML,
|
|
5117
|
+
D as getStrings,
|
|
5118
|
+
kt as normalizeTextPaste
|
|
4876
5119
|
};
|