md-editor-v3
Version:
Markdown editor for vue3, 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) • 9.21 kB
JavaScript
;const o=require("vue"),R=require("./config.cjs"),x=require("./event-bus.cjs"),F=require("./index5.cjs"),P=require("@vavt/util"),G=`.${R.prefix}-preview > [data-line]`,D=(e,l)=>+getComputedStyle(e).getPropertyValue(l).replace("px",""),j=(e,l)=>{const I=P.debounce(()=>{e.removeEventListener("scroll",c),e.addEventListener("scroll",c),l.removeEventListener("scroll",c),l.addEventListener("scroll",c)},50),c=k=>{const u=e.clientHeight,y=l.clientHeight,m=e.scrollHeight,d=l.scrollHeight,s=(m-u)/(d-y);k.target===e?(l.removeEventListener("scroll",c),l.scrollTo({top:e.scrollTop/s}),I()):(e.removeEventListener("scroll",c),e.scrollTo({top:l.scrollTop*s}),I())};return[()=>{I().finally(()=>{e.dispatchEvent(new Event("scroll"))})},()=>{e.removeEventListener("scroll",c),l.removeEventListener("scroll",c)}]},U=(e,l,I)=>{const{view:c}=I,k=P.createSmoothScroll(),u=r=>c.lineBlockAt(c.state.doc.line(r+1).from).top,y=r=>c.lineBlockAt(c.state.doc.line(r+1).from).bottom;let m=[],d=[],s=[];const N=()=>{m=[],d=Array.from(l.querySelectorAll(G)),s=d.map(n=>Number(n.dataset.line));const r=[...s],{lines:h}=c.state.doc;r[0]!==0&&r.unshift(0);let C=r.shift()||0,t=r.shift()||h;for(let n=0;n<h;n++)n===t&&(C=n,t=r.shift()||h),m.push({start:C,end:t-1})},w=(r,h)=>{let C=1;for(let t=d.length-1;t-1>=0;t--){const n=d[t];if(n.offsetTop<=h){C=Number(n.dataset.line);break}}for(let t=m.length-1;t>=0;t--)if(u(m[t].start)<=r){C=C<m[t].start?C:m[t].start;break}return C};let A=0,$=0;const V=()=>{if($!==0)return!1;A++;const{scrollDOM:r}=c;let h=D(l,"padding-block-start");const C=c.lineBlockAtHeight(r.scrollTop),{number:t}=c.state.doc.lineAt(C.from),n=m[t-1];if(!n)return!1;let H=1;const f=l.querySelector(`[data-line="${n.start}"]`)||l.firstElementChild?.firstElementChild,v=l.querySelector(`[data-line="${n.end+1}"]`)||l.lastElementChild?.lastElementChild,g=r.scrollHeight-r.clientHeight,i=l.scrollHeight-l.clientHeight;let T=u(n.start),p=y(n.end),a=f.offsetTop,S=v.offsetTop-a;T===0&&(a=0,f===v?(h=0,S=0):S=v.offsetTop),H=(r.scrollTop-T)/(p-T);const M=v==l.lastElementChild?.lastElementChild?v.offsetTop+v.clientHeight:v.offsetTop;if(p>=g||M>i){const L=w(g,i);T=u(L),H=(r.scrollTop-T)/(g-T);const E=l.querySelector(`[data-line="${L}"]`);T>0&&E&&(a=E.offsetTop),S=i-a+D(l,"padding-block-start")}const q=a-h+S*H;k(l,q,()=>{A--})},B=()=>{if(A!==0)return;$++;const{scrollDOM:r}=c,h=l.scrollTop,C=l.scrollHeight,t=r.scrollHeight-r.clientHeight,n=l.scrollHeight-l.clientHeight;let H=l.firstElementChild?.firstElementChild,f=l.firstElementChild?.lastElementChild;if(s.length>0){let L=Math.ceil(s[s.length-1]*(h/C)),E=s.findLastIndex(b=>b<=L);E=E===-1?0:E,L=s[E];for(let b=E;b>=0&&b<s.length;)if(d[b].offsetTop>h){if(b-1>=0){b--;continue}L=-1,E=-1;break}else{if(b+1<s.length&&d[b+1].offsetTop<h){b++;continue}L=s[b],E=b;break}switch(E){case-1:{H=l.firstElementChild?.firstElementChild,f=d[0];break}case s.length-1:{H=d[E],f=l.firstElementChild?.lastElementChild;break}default:H=d[E],f=d[E+1]}}let v=H===l.firstElementChild?.firstElementChild?0:H.offsetTop-D(H,"margin-block-start"),g=f.offsetTop,i=0;const{start:T,end:p}=m[Number(H.dataset.line||0)];let a=u(T);const S=u(p+1===c.state.doc.lines?p:p+1);let M=0;const q=f==l.lastElementChild?.lastElementChild?f.offsetTop+f.offsetHeight:f.offsetTop;if(S>t||q>n){const L=w(t,n),E=l.querySelector(`[data-line="${L}"]`);v=E?E.offsetTop-D(E,"margin-block-start"):v,a=u(L),i=(h-v)/(n-v),M=t-a}else H===l.firstElementChild?.firstElementChild?(H===f&&(g=f.offsetTop+f.offsetHeight+D(f,"margin-block-end")),M=S,a=0,i=Math.max(h/g,0)):(i=Math.max((h-v)/(g-v),0),M=S-a);k(e,a+M*i,()=>{$--})},O=r=>{const{scrollDOM:h,contentHeight:C}=c,t=h.clientHeight;if(C<=t||l.firstElementChild.clientHeight<=l.clientHeight||c.state.doc.lines<=m[m.length-1]?.end)return!1;r.target===e?V():B()};return[()=>{N(),e.addEventListener("scroll",O),l.addEventListener("scroll",O),e.dispatchEvent(new Event("scroll"))},()=>{e.removeEventListener("scroll",O),l.removeEventListener("scroll",O)}]},z={tocItem:{type:Object,default:()=>({})},mdHeadingId:{type:Function,default:()=>{}},onActive:{type:Function,default:()=>{}},onClick:{type:Function,default:()=>{}},scrollElementOffsetTop:{type:Number,default:0}},W=o.defineComponent({props:z,setup(e){const l=o.inject("scrollElementRef"),I=o.inject("roorNodeRef"),c=o.ref();o.watch(()=>e.tocItem.active,u=>{u&&e.onActive(e.tocItem,c.value)}),o.onMounted(()=>{e.tocItem.active&&e.onActive(e.tocItem,c.value)});const k=u=>{if(u.stopPropagation(),e.onClick(u,e.tocItem),u.defaultPrevented)return;const y=e.mdHeadingId({text:e.tocItem.text,level:e.tocItem.level,index:e.tocItem.index,currentToken:e.tocItem.currentToken,nextToken:e.tocItem.nextToken}),m=I.value.getElementById(y),d=l.value;if(m&&d){let s=m.offsetParent,N=m.offsetTop;if(d.contains(s))for(;s&&d!=s;)N+=s?.offsetTop,s=s?.offsetParent;const w=m.previousElementSibling;let A=0;w||(A=D(m,"margin-block-start")),d?.scrollTo({top:N-e.scrollElementOffsetTop-A,behavior:"smooth"})}};return()=>o.createVNode("div",{ref:c,class:[`${R.prefix}-catalog-link`,e.tocItem.active&&`${R.prefix}-catalog-active`],onClick:k},[o.createVNode("span",{title:e.tocItem.text},[e.tocItem.text]),e.tocItem.children&&e.tocItem.children.length>0&&o.createVNode("div",{class:`${R.prefix}-catalog-wrapper`},[e.tocItem.children.map(u=>o.createVNode(W,{mdHeadingId:e.mdHeadingId,key:`${e.tocItem.text}-link-${u.level}-${u.text}`,tocItem:u,onActive:e.onActive,onClick:e.onClick,scrollElementOffsetTop:e.scrollElementOffsetTop},null))])])}}),J={editorId:{type:String,default:void 0},class:{type:String,default:""},mdHeadingId:{type:Function,default:({text:e})=>e},scrollElement:{type:[String,Object],default:void 0},theme:{type:String,default:"light"},offsetTop:{type:Number,default:20},scrollElementOffsetTop:{type:Number,default:0},onClick:{type:Function,default:void 0},onActive:{type:Function,default:void 0},isScrollElementInShadow:{type:Boolean,default:!1},syncWith:{type:String,default:"preview"},catalogMaxDepth:{type:Number,default:void 0}},_=o.defineComponent({name:"MdCatalog",props:J,emits:["onClick","onActive"],setup(e,l){const I=e.editorId,c=`#${I}-preview-wrapper`,k=o.reactive({list:[],show:!1,scrollElement:e.scrollElement||c}),u=o.shallowRef(),y=o.ref(),m=o.ref(),d=o.ref(),s=o.ref(),N=o.shallowRef(),w=o.ref({});o.provide("scrollElementRef",m),o.provide("roorNodeRef",s);const A=o.computed(()=>{const t=[];return k.list.forEach((n,H)=>{if(e.catalogMaxDepth&&n.level>e.catalogMaxDepth)return;const{text:f,level:v,line:g}=n,i={level:v,text:f,line:g,index:H+1,active:u.value===n};if(t.length===0)t.push(i);else{let T=t[t.length-1];if(i.level>T.level)for(let p=T.level+1;p<=6;p++){const{children:a}=T;if(!a){T.children=[i];break}if(T=a[a.length-1],i.level<=T.level){a.push(i);break}}else t.push(i)}}),t}),$=()=>{if(k.scrollElement instanceof HTMLElement)return k.scrollElement;let t=document;return(k.scrollElement===c||e.isScrollElementInShadow)&&(t=y.value?.getRootNode()),t.querySelector(k.scrollElement)},V=t=>{if(t.length===0)return u.value=void 0,k.list=[],!1;const{activeHead:n,activeIndex:H}=t.reduce((g,i,T)=>{let p=0;if(e.syncWith==="preview"){const a=s.value?.getElementById(e.mdHeadingId({text:i.text,level:i.level,index:T+1,currentToken:i.currentToken,nextToken:i.nextToken}));a instanceof HTMLElement&&(p=F.getRelativeTop(a,m.value))}else{const a=N.value;if(a){const S=a.lineBlockAt(a.state.doc.line(i.line+1).from).top,M=a.scrollDOM.scrollTop;p=S-M}}return p<e.offsetTop&&p>g.minTop?{activeHead:i,activeIndex:T,minTop:p}:g},{activeHead:t[0],activeIndex:0,minTop:Number.MIN_SAFE_INTEGER});let f=n;const{catalogMaxDepth:v}=e;if(v&&f.level>v){for(let g=H;g>=0;g--){const i=t[g];if(i.level<=v){f=i;break}}if(f.level>v){const g=t.find(i=>i.level<=v);g&&(f=g)}}u.value=f,k.list=t},B=(t,n)=>{w.value.top=n.offsetTop+D(n,"padding-block-start")+"px",e.onActive?.(t,n),l.emit("onActive",t,n)},O=()=>{V(k.list)},r=t=>{if(d.value?.removeEventListener("scroll",O),e.syncWith==="editor")d.value=N.value?.scrollDOM;else{const n=$();m.value=n,d.value=n===document.documentElement?document:n}V(t),d.value?.addEventListener("scroll",O)},h=t=>{N.value=t};o.watch([()=>e.syncWith,N,()=>e.catalogMaxDepth],()=>{r(k.list)}),o.onMounted(()=>{s.value=y.value.getRootNode(),x.bus.on(I,{name:x.CATALOG_CHANGED,callback:r}),x.bus.on(I,{name:x.GET_EDITOR_VIEW,callback:h}),x.bus.emit(I,x.PUSH_CATALOG),x.bus.emit(I,x.SEND_EDITOR_VIEW)}),o.onBeforeUnmount(()=>{x.bus.remove(I,x.CATALOG_CHANGED,r),x.bus.remove(I,x.GET_EDITOR_VIEW,h),d.value?.removeEventListener("scroll",O)});const C=(t,n)=>{e.onClick?.(t,n),l.emit("onClick",t,n)};return()=>o.createVNode("div",{class:[`${R.prefix}-catalog`,e.theme==="dark"&&`${R.prefix}-catalog-dark`,e.class||""],ref:y},[A.value.length>0&&o.createVNode(o.Fragment,null,[o.createVNode("div",{class:`${R.prefix}-catalog-indicator`,style:w.value},null),o.createVNode("div",{class:`${R.prefix}-catalog-container`},[A.value.map(t=>o.createVNode(W,{mdHeadingId:e.mdHeadingId,tocItem:t,key:`link-${t.level}-${t.text}`,onActive:B,onClick:C,scrollElementOffsetTop:e.scrollElementOffsetTop},null))])])])}});_.install=e=>(e.component(_.name,_),e);exports.MdCatalog=_;exports.scrollAuto=U;exports.scrollAutoWithScale=j;