UNPKG

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
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 };