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...
2 lines (1 loc) • 8.29 kB
JavaScript
;const $=require("react/jsx-runtime"),d=require("react"),B=require("./config.cjs"),A=require("./event-bus.cjs"),_=require("./index2.cjs"),W=require("@vavt/util"),J=`.${B.prefix}-preview > [data-line]`,I=(t,e)=>+getComputedStyle(t).getPropertyValue(e).replace("px",""),K=(t,e)=>{const M=W.debounce(()=>{t.removeEventListener("scroll",o),t.addEventListener("scroll",o),e.removeEventListener("scroll",o),e.addEventListener("scroll",o)},50),o=w=>{const S=t.clientHeight,b=e.clientHeight,g=t.scrollHeight,a=e.scrollHeight,h=(g-S)/(a-b);w.target===t?(e.removeEventListener("scroll",o),e.scrollTo({top:t.scrollTop/h}),M()):(t.removeEventListener("scroll",o),t.scrollTo({top:e.scrollTop*h}),M())};return[()=>{M().finally(()=>{t.dispatchEvent(new Event("scroll"))})},()=>{t.removeEventListener("scroll",o),e.removeEventListener("scroll",o)}]},Q=(t,e,M)=>{const{view:o}=M,w=W.createSmoothScroll(),S=s=>o.lineBlockAt(o.state.doc.line(s+1).from).top,b=s=>o.lineBlockAt(o.state.doc.line(s+1).from).bottom;let g=[],a=[],h=[];const O=()=>{g=[],a=Array.from(e.querySelectorAll(J)),h=a.map(r=>Number(r.dataset.line));const s=[...h],{lines:m}=o.state.doc;s[0]!==0&&s.unshift(0);let T=s.shift()||0,i=s.shift()||m;for(let r=0;r<m;r++)r===i&&(T=r,i=s.shift()||m),g.push({start:T,end:i-1})},D=(s,m)=>{let T=1;for(let i=a.length-1;i-1>=0;i--){const r=a[i];if(r.offsetTop<=m){T=Number(r.dataset.line);break}}for(let i=g.length-1;i>=0;i--)if(S(g[i].start)<=s){T=T<g[i].start?T:g[i].start;break}return T};let N=0,q=0;const j=()=>{if(q!==0)return!1;N++;const{scrollDOM:s}=o;let m=I(e,"padding-block-start");const T=o.lineBlockAtHeight(s.scrollTop),{number:i}=o.state.doc.lineAt(T.from),r=g[i-1];if(!r)return!1;let x=1;const v=e.querySelector(`[data-line="${r.start}"]`)||e.firstElementChild?.firstElementChild,E=e.querySelector(`[data-line="${r.end+1}"]`)||e.lastElementChild?.lastElementChild,n=s.scrollHeight-s.clientHeight,u=e.scrollHeight-e.clientHeight;let C=S(r.start),y=b(r.end),c=v.offsetTop,p=E.offsetTop-c;C===0&&(c=0,v===E?(m=0,p=0):p=E.offsetTop),x=(s.scrollTop-C)/(y-C);const H=E==e.lastElementChild?.lastElementChild?E.offsetTop+E.clientHeight:E.offsetTop;if(y>=n||H>u){const f=D(n,u);C=S(f),x=(s.scrollTop-C)/(n-C);const l=e.querySelector(`[data-line="${f}"]`);C>0&&l&&(c=l.offsetTop),p=u-c+I(e,"padding-block-start")}const k=c-m+p*x;w(e,k,()=>{N--})},P=()=>{if(N!==0)return;q++;const{scrollDOM:s}=o,m=e.scrollTop,T=e.scrollHeight,i=s.scrollHeight-s.clientHeight,r=e.scrollHeight-e.clientHeight;let x=e.firstElementChild?.firstElementChild,v=e.firstElementChild?.lastElementChild;if(h.length>0){let f=Math.ceil(h[h.length-1]*(m/T)),l=h.findLastIndex(L=>L<=f);l=l===-1?0:l,f=h[l];for(let L=l;L>=0&&L<h.length;)if(a[L].offsetTop>m){if(L-1>=0){L--;continue}f=-1,l=-1;break}else{if(L+1<h.length&&a[L+1].offsetTop<m){L++;continue}f=h[L],l=L;break}switch(l){case-1:{x=e.firstElementChild?.firstElementChild,v=a[0];break}case h.length-1:{x=a[l],v=e.firstElementChild?.lastElementChild;break}default:x=a[l],v=a[l+1]}}let E=x===e.firstElementChild?.firstElementChild?0:x.offsetTop-I(x,"margin-block-start"),n=v.offsetTop,u=0;const{start:C,end:y}=g[Number(x.dataset.line||0)];let c=S(C);const p=S(y+1===o.state.doc.lines?y:y+1);let H=0;const k=v==e.lastElementChild?.lastElementChild?v.offsetTop+v.offsetHeight:v.offsetTop;if(p>i||k>r){const f=D(i,r),l=e.querySelector(`[data-line="${f}"]`);E=l?l.offsetTop-I(l,"margin-block-start"):E,c=S(f),u=(m-E)/(r-E),H=i-c}else x===e.firstElementChild?.firstElementChild?(x===v&&(n=v.offsetTop+v.offsetHeight+I(v,"margin-block-end")),H=p,c=0,u=Math.max(m/n,0)):(u=Math.max((m-E)/(n-E),0),H=p-c);w(t,c+H*u,()=>{q--})},R=s=>{const{scrollDOM:m,contentHeight:T}=o,i=m.clientHeight;if(T<=i||e.firstElementChild.clientHeight<=e.clientHeight||o.state.doc.lines<=g[g.length-1]?.end)return!1;s.target===t?j():P()};return[()=>{O(),t.addEventListener("scroll",R),e.addEventListener("scroll",R),t.dispatchEvent(new Event("scroll"))},()=>{t.removeEventListener("scroll",R),e.removeEventListener("scroll",R)}]},F=d.createContext({scrollElementRef:void 0,rootNodeRef:void 0}),U=({tocItem:t,mdHeadingId:e,onActive:M,onClick:o,scrollElementOffsetTop:w=0})=>{const{scrollElementRef:S,rootNodeRef:b}=d.useContext(F),g=d.useRef(null);return d.useEffect(()=>{t.active&&M(t,g.current)},[M,t,t.active]),$.jsxs("div",{ref:g,className:_.classnames([`${B.prefix}-catalog-link`,t.active&&`${B.prefix}-catalog-active`]),onClick:a=>{if(a.stopPropagation(),o?.(a,t),a.defaultPrevented)return;const h=e({text:t.text,level:t.level,index:t.index,currentToken:t.currentToken,nextToken:t.nextToken}),O=b?.current.getElementById(h),D=S?.current;if(O&&D){let N=O.offsetParent,q=O.offsetTop;if(D.contains(N))for(;N&&D!=N;)q+=N?.offsetTop,N=N?.offsetParent;const j=O.previousElementSibling;let P=0;j||(P=I(O,"margin-block-start")),D?.scrollTo({top:q-w-P,behavior:"smooth"})}},children:[$.jsx("span",{title:t.text,children:t.text}),t.children&&t.children.length>0&&$.jsx("div",{className:`${B.prefix}-catalog-wrapper`,children:t.children.map(a=>$.jsx(U,{mdHeadingId:e,tocItem:a,onActive:M,onClick:o,scrollElementOffsetTop:w},`${t.text}-link-${a.level}-${a.text}`))})]})},X=d.memo(U),Y=t=>{const{editorId:e,mdHeadingId:M=B.defaultProps.mdHeadingId,theme:o="light",offsetTop:w=20,syncWith:S="preview",catalogMaxDepth:b}=t,g=d.useMemo(()=>`#${e}-preview-wrapper`,[e]),[a,h]=d.useState([]),[O,D]=d.useState(),N=d.useRef(null),q=d.useRef(null),j=d.useRef(void 0),P=d.useRef(null),[R,s]=d.useState(),[m,T]=d.useState({}),i=d.useMemo(()=>{const n=[];return a.forEach((u,C)=>{if(b&&u.level>b)return;const{text:y,level:c,line:p}=u,H={level:c,text:y,line:p,index:C+1,active:O===u};if(n.length===0)n.push(H);else{let k=n[n.length-1];if(H.level>k.level)for(let f=k.level+1;f<=6;f++){const{children:l}=k;if(!l){k.children=[H];break}if(k=l[l.length-1],H.level<=k.level){l.push(H);break}}else n.push(H)}}),n},[O,a,b]),[r]=d.useState(()=>t.scrollElement||`#${e}-preview-wrapper`),x=d.useCallback(()=>{if(r instanceof HTMLElement)return r;let n=document;return(r===g||t.isScrollElementInShadow)&&(n=N.current?.getRootNode()),n.querySelector(r)},[g,t.isScrollElementInShadow,r]),v=d.useCallback((n,u)=>{T({top:u.offsetTop+I(u,"padding-block-start")+"px"}),t.onActive?.(n,u)},[t]);d.useEffect(()=>{P.current=N.current.getRootNode()},[]),d.useEffect(()=>{let n=[];const u=c=>{if(c.length===0)return D(void 0),h([]),n=c,!1;const{activeHead:p,activeIndex:H}=c.reduce((f,l,L)=>{let G=0;if(S==="preview"){const V=P.current?.getElementById(M({text:l.text,level:l.level,index:L+1,currentToken:l.currentToken,nextToken:l.nextToken}));V instanceof HTMLElement&&(G=_.getRelativeTop(V,q.current))}else if(R){const V=R.lineBlockAt(R.state.doc.line(l.line+1).from).top,z=R.scrollDOM.scrollTop;G=V-z}return G<w&&G>f.minTop?{activeHead:l,activeIndex:L,minTop:G}:f},{activeHead:c[0],activeIndex:0,minTop:Number.MIN_SAFE_INTEGER});let k=p;if(b&&k.level>b){for(let f=H;f>=0;f--){const l=c[f];if(l.level<=b){k=l;break}}if(k.level>b){const f=c.find(l=>l.level<=b);f&&(k=f)}}D(k),h(c),n=c},C=()=>{u(n)},y=c=>{if(j.current?.removeEventListener("scroll",C),S==="editor")j.current=R?.scrollDOM;else{const p=x();q.current=p,j.current=p===document.documentElement?document:p}u(c),j.current?.addEventListener("scroll",C)};return A.bus.on(e,{name:A.CATALOG_CHANGED,callback:y}),A.bus.emit(e,A.PUSH_CATALOG),()=>{A.bus.remove(e,A.CATALOG_CHANGED,y),j.current?.removeEventListener("scroll",C)}},[w,M,x,e,S,R,b]);const E=d.useMemo(()=>({scrollElementRef:q,rootNodeRef:P}),[]);return d.useEffect(()=>{const n=u=>{s(u)};return A.bus.on(e,{name:A.GET_EDITOR_VIEW,callback:n}),A.bus.emit(e,A.SEND_EDITOR_VIEW),()=>{A.bus.remove(e,A.GET_EDITOR_VIEW,n)}},[e]),$.jsx(F.Provider,{value:E,children:$.jsx("div",{className:_.classnames([`${B.prefix}-catalog`,o==="dark"&&`${B.prefix}-catalog-dark`,t.className||""]),style:t.style,ref:N,children:i.length>0&&$.jsxs($.Fragment,{children:[$.jsx("div",{className:`${B.prefix}-catalog-indicator`,style:m}),$.jsx("div",{className:`${B.prefix}-catalog-container`,children:i.map(n=>$.jsx(X,{mdHeadingId:M,tocItem:n,onActive:v,onClick:t.onClick,scrollElementOffsetTop:t.scrollElementOffsetTop},`link-${n.level}-${n.text}`))})]})})})},Z=d.memo(Y);exports.MdCatalog=Z;exports.scrollAuto=Q;exports.scrollAutoWithScale=K;