md-editor-rt
Version:
Markdown editor for react, developed in jsx and typescript, dark theme、beautify content by prettier、render articles directly、paste or clip the picture and upload it...
372 lines (371 loc) • 12.6 kB
JavaScript
import { jsxs as Y, jsx as R, Fragment as le } from "react/jsx-runtime";
import { createContext as oe, useContext as ne, useRef as U, useEffect as z, memo as re, useMemo as J, useState as F, useCallback as K } from "react";
import { p as B, d as se } from "./config.mjs";
import { c as Z, a as ie } from "./index3.mjs";
import { b as G, k as Q, l as ce, G as X, S as ae } from "./event-name.mjs";
import { createSmoothScroll as fe, debounce as de } from "@vavt/util";
const me = `.${B}-preview > [data-line]`, V = (t, e) => +getComputedStyle(t).getPropertyValue(e).replace("px", ""), Le = (t, e) => {
const b = de(() => {
t.removeEventListener("scroll", n), t.addEventListener("scroll", n), e.removeEventListener("scroll", n), e.addEventListener("scroll", n);
}, 50), n = (A) => {
const L = t.clientHeight, $ = e.clientHeight, g = t.scrollHeight, s = e.scrollHeight, u = (g - L) / (s - $);
A.target === t ? (e.removeEventListener("scroll", n), e.scrollTo({
top: t.scrollTop / u
// behavior: 'smooth'
}), b()) : (t.removeEventListener("scroll", n), t.scrollTo({
top: e.scrollTop * u
// behavior: 'smooth'
}), b());
};
return [
() => {
b().finally(() => {
t.dispatchEvent(new Event("scroll"));
});
},
() => {
t.removeEventListener("scroll", n), e.removeEventListener("scroll", n);
}
];
}, Se = (t, e, b) => {
const { view: n } = b, A = fe(), L = (c) => n.lineBlockAt(n.state.doc.line(c + 1).from).top, $ = (c) => n.lineBlockAt(n.state.doc.line(c + 1).from).bottom;
let g = [], s = [], u = [];
const w = () => {
g = [], s = Array.from(
e.querySelectorAll(me)
), u = s.map((a) => Number(a.dataset.line));
const c = [...u], { lines: v } = n.state.doc;
let T = c.shift() || 0, o = c.shift() || v;
for (let a = 0; a < v; a++)
a === o && (T = a, o = c.shift() || v), g.push({
start: T,
end: o - 1
});
}, x = (c, v) => {
let T = 1;
for (let o = s.length - 1; o - 1 >= 0; o--) {
const a = s[o], f = s[o - 1];
if (a.offsetTop + a.offsetHeight > v && f.offsetTop < v) {
T = Number(f.dataset.line);
break;
}
}
for (let o = g.length - 1; o >= 0; o--) {
const a = $(g[o].end), f = L(g[o].start);
if (a > c && f <= c) {
T = T < g[o].start ? T : g[o].start;
break;
}
}
return T;
};
let p = 0, y = 0;
const P = () => {
var D, _, W;
if (y !== 0)
return !1;
p++;
const { scrollDOM: c, contentHeight: v } = n;
let T = V(e, "padding-top");
const o = n.lineBlockAtHeight(c.scrollTop), { number: a } = n.state.doc.lineAt(o.from), f = g[a - 1];
if (!f)
return !1;
let l = 1;
const i = e.querySelector(`[data-line="${f.start}"]`) || ((D = e.firstElementChild) == null ? void 0 : D.firstElementChild), m = e.querySelector(`[data-line="${f.end + 1}"]`) || ((_ = e.lastElementChild) == null ? void 0 : _.lastElementChild), N = c.scrollHeight - c.clientHeight, h = e.scrollHeight - e.clientHeight;
let H = L(f.start), d = $(f.end), r = i.offsetTop, S = m.offsetTop - r;
H === 0 && (r = 0, i === m ? (T = 0, d = v - c.offsetHeight, S = h) : S = m.offsetTop), l = (c.scrollTop - H) / (d - H);
const C = m == ((W = e.lastElementChild) == null ? void 0 : W.lastElementChild) ? m.offsetTop + m.clientHeight : m.offsetTop;
if (d >= N || C > h) {
const j = x(N, h);
H = L(j), l = (c.scrollTop - H) / (N - H);
const O = e.querySelector(`[data-line="${j}"]`);
H > 0 && O && (r = O.offsetTop), S = h - r + V(e, "padding-top");
}
const I = r - T + S * l;
A(e, I, () => {
p--;
});
}, k = () => {
var C, I, D, _, W, j;
if (p !== 0)
return;
y++;
const { scrollDOM: c } = n, v = e.scrollTop, T = e.scrollHeight, o = c.scrollHeight - c.clientHeight, a = e.scrollHeight - e.clientHeight;
let f = (C = e.firstElementChild) == null ? void 0 : C.firstElementChild, l = (I = e.firstElementChild) == null ? void 0 : I.lastElementChild;
if (u.length > 0) {
let O = Math.ceil(
u[u.length - 1] * (v / T)
), E = u.findLastIndex((M) => M <= O);
E = E === -1 ? 0 : E, O = u[E];
for (let M = E; M >= 0 && M < u.length; )
if (s[M].offsetTop > v) {
if (M - 1 >= 0) {
M--;
continue;
}
O = -1, E = M;
break;
} else {
if (M + 1 < u.length && s[M + 1].offsetTop < v) {
M++;
continue;
}
O = u[M], E = M;
break;
}
switch (E) {
case -1: {
f = (D = e.firstElementChild) == null ? void 0 : D.firstElementChild, l = s[E];
break;
}
case u.length - 1: {
f = s[E], l = (_ = e.firstElementChild) == null ? void 0 : _.lastElementChild;
break;
}
default:
f = s[E], l = s[E + 1 === s.length ? E : E + 1];
}
}
let i = f === ((W = e.firstElementChild) == null ? void 0 : W.firstElementChild) ? 0 : f.offsetTop - V(f, "margin-top"), m = l.offsetTop, N = 0;
const { start: h, end: H } = g[Number(f.dataset.line || 0)];
let d = L(h);
const r = L(
H + 1 === n.state.doc.lines ? H : H + 1
);
let S = 0;
if (r > o || l.offsetTop + l.offsetHeight > a) {
const O = x(o, a), E = e.querySelector(`[data-line="${O}"]`);
i = E ? E.offsetTop - V(E, "margin-top") : i, d = L(O), N = (v - i) / (a - i), S = o - d;
} else f === ((j = e.firstElementChild) == null ? void 0 : j.firstElementChild) ? (f === l && (m = l.offsetTop + l.offsetHeight + +getComputedStyle(l).marginBottom.replace("px", "")), S = r, N = Math.max(v / m, 0)) : (N = Math.max(
(v - i) / (m - i),
0
), S = r - d);
A(t, d + S * N, () => {
y--;
});
}, q = (c) => {
var a;
const { scrollDOM: v, contentHeight: T } = n, o = v.clientHeight;
if (T <= o || e.firstElementChild.clientHeight <= e.clientHeight || n.state.doc.lines <= ((a = g[g.length - 1]) == null ? void 0 : a.end))
return !1;
c.target === t ? P() : k();
};
return [
() => {
w(), t.addEventListener("scroll", q), e.addEventListener("scroll", q), t.dispatchEvent(new Event("scroll"));
},
() => {
t.removeEventListener("scroll", q), e.removeEventListener("scroll", q);
}
];
}, ee = oe({
scrollElementRef: void 0,
rootNodeRef: void 0
}), te = ({
tocItem: t,
mdHeadingId: e,
onActive: b,
onClick: n,
scrollElementOffsetTop: A = 0
}) => {
const { scrollElementRef: L, rootNodeRef: $ } = ne(ee), g = U(null);
return z(() => {
t.active && b(t, g.current);
}, [b, t, t.active]), /* @__PURE__ */ Y(
"div",
{
ref: g,
className: Z([
`${B}-catalog-link`,
t.active && `${B}-catalog-active`
]),
onClick: (s) => {
if (s.stopPropagation(), n == null || n(s, t), s.defaultPrevented)
return;
const u = e(t.text, t.level, t.index), w = $ == null ? void 0 : $.current.getElementById(u), x = L == null ? void 0 : L.current;
if (w && x) {
let p = w.offsetParent, y = w.offsetTop;
if (x.contains(p))
for (; p && x != p; )
y += p == null ? void 0 : p.offsetTop, p = p == null ? void 0 : p.offsetParent;
const P = w.previousElementSibling;
let k = 0;
P || (k = V(w, "margin-top")), x == null || x.scrollTo({
top: y - A - k,
behavior: "smooth"
});
}
},
children: [
/* @__PURE__ */ R("span", { title: t.text, children: t.text }),
t.children && t.children.length > 0 && /* @__PURE__ */ R("div", { className: `${B}-catalog-wrapper`, children: t.children.map((s) => /* @__PURE__ */ R(
te,
{
mdHeadingId: e,
tocItem: s,
onActive: b,
onClick: n,
scrollElementOffsetTop: A
},
`${t.text}-link-${s.level}-${s.text}`
)) })
]
}
);
}, he = (t) => {
const {
editorId: e,
mdHeadingId: b = se.mdHeadingId,
theme: n = "light",
offsetTop: A = 20,
syncWith: L = "preview"
} = t, $ = J(() => `#${e}-preview-wrapper`, [e]), [g, s] = F([]), [u, w] = F(), x = U(null), p = U(), y = U(), P = U(), [k, q] = F(), [c, v] = F({}), T = J(() => {
const l = [];
return g.forEach((i, m) => {
if (t.catalogMaxDepth && i.level > t.catalogMaxDepth)
return;
const { text: N, level: h, line: H } = i, d = {
level: h,
text: N,
line: H,
index: m + 1,
active: u === i
};
if (l.length === 0)
l.push(d);
else {
let r = l[l.length - 1];
if (d.level > r.level)
for (let S = r.level + 1; S <= 6; S++) {
const { children: C } = r;
if (!C) {
r.children = [d];
break;
}
if (r = C[C.length - 1], d.level <= r.level) {
C.push(d);
break;
}
}
else
l.push(d);
}
}), l;
}, [u, g, t.catalogMaxDepth]), [o] = F(() => t.scrollElement || `#${e}-preview-wrapper`), a = K(() => {
var i;
if (o instanceof HTMLElement)
return o;
let l = document;
return (o === $ || t.isScrollElementInShadow) && (l = (i = x.current) == null ? void 0 : i.getRootNode()), l.querySelector(o);
}, [$, t.isScrollElementInShadow, o]), f = K(
(l, i) => {
var m;
v({
top: i.offsetTop + V(i, "padding-top") + "px"
}), (m = t.onActive) == null || m.call(t, l, i);
},
[t]
);
return z(() => {
P.current = x.current.getRootNode();
}, []), z(() => {
let l = [];
const i = (h) => {
if (h.length === 0)
return w(void 0), s([]), l = h, !1;
const { activeHead: H } = h.reduce(
(d, r, S) => {
var I;
let C = 0;
if (L === "preview") {
const D = (I = P.current) == null ? void 0 : I.getElementById(
b(r.text, r.level, S + 1)
);
D instanceof HTMLElement && (C = ie(D, p.current));
} else if (k) {
const D = k.lineBlockAt(
k.state.doc.line(r.line + 1).from
).top, _ = k.scrollDOM.scrollTop;
C = D - _;
}
return C < A && C > d.minTop ? {
activeHead: r,
minTop: C
} : d;
},
{
activeHead: h[0],
minTop: Number.MIN_SAFE_INTEGER
}
);
w(H), s(h), l = h;
}, m = () => {
i(l);
}, N = (h) => {
var H, d;
if ((H = y.current) == null || H.removeEventListener("scroll", m), L === "editor")
y.current = k == null ? void 0 : k.scrollDOM;
else {
const r = a();
p.current = r, y.current = r === document.documentElement ? document : r;
}
i(h), (d = y.current) == null || d.addEventListener("scroll", m);
};
return G.on(e, {
name: Q,
callback: N
}), G.emit(e, ce), () => {
var h;
G.remove(e, Q, N), (h = y.current) == null || h.removeEventListener("scroll", m);
};
}, [A, b, a, e, L, k]), z(() => {
const l = (i) => {
q(i);
};
return G.on(e, {
name: X,
callback: l
}), G.emit(e, ae), () => {
G.remove(e, X, l);
};
}, [e]), /* @__PURE__ */ R(
ee.Provider,
{
value: {
scrollElementRef: p,
rootNodeRef: P
},
children: /* @__PURE__ */ R(
"div",
{
className: Z([
`${B}-catalog`,
n === "dark" && `${B}-catalog-dark`,
t.className || ""
]),
style: t.style,
ref: x,
children: T.length > 0 && /* @__PURE__ */ Y(le, { children: [
/* @__PURE__ */ R("div", { className: `${B}-catalog-indicator`, style: c }),
/* @__PURE__ */ R("div", { className: `${B}-catalog-container`, children: T.map((l) => /* @__PURE__ */ R(
te,
{
mdHeadingId: b,
tocItem: l,
onActive: f,
onClick: t.onClick,
scrollElementOffsetTop: t.scrollElementOffsetTop
},
`link-${l.level}-${l.text}`
)) })
] })
}
)
}
);
}, Ce = re(he);
export {
Ce as M,
Le as a,
Se as s
};