You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

codejar.min.js 4.3KB

12345
  1. /*!
  2. * CodeJar 3.1.0 (https://github.com/antonmedv/codejar)
  3. * Copyright (c) 2020, Anton Medvedev, MIT
  4. */
  5. function CodeJar(t,e,n={}){const o=Object.assign({tab:"\t",indentOn:/{$/},n);let r,s,i=[],c=[],d=-1,a=!1,f=navigator.userAgent.toLowerCase().indexOf("firefox")>-1;t.setAttribute("contentEditable",f?"true":"plaintext-only"),t.setAttribute("spellcheck","false"),t.style.outline="none",t.style.overflowWrap="break-word",t.style.overflowY="auto",t.style.resize="vertical",t.style.whiteSpace="pre-wrap",e(t);const l=E(()=>{const n=y();e(t),m(n)},30);let u=!1;const p=t=>!T(t)&&!v(t)&&"Meta"!==t.key&&"Control"!==t.key&&"Alt"!==t.key&&!t.key.startsWith("Arrow"),g=E(t=>{p(t)&&(O(),u=!1)},300),h=(e,n)=>{i.push([e,n]),t.addEventListener(e,n)};function y(){const e=window.getSelection(),n={start:0,end:0,dir:void 0};return C(t,t=>{if(t===e.anchorNode&&t===e.focusNode)return n.start+=e.anchorOffset,n.end+=e.focusOffset,n.dir=e.anchorOffset<=e.focusOffset?"->":"<-","stop";if(t===e.anchorNode){if(n.start+=e.anchorOffset,n.dir)return"stop";n.dir="->"}else if(t===e.focusNode){if(n.end+=e.focusOffset,n.dir)return"stop";n.dir="<-"}t.nodeType===Node.TEXT_NODE&&("->"!=n.dir&&(n.start+=t.nodeValue.length),"<-"!=n.dir&&(n.end+=t.nodeValue.length))}),n}function m(e){const n=window.getSelection();let o,r,s=0,i=0;if(e.dir||(e.dir="->"),e.start<0&&(e.start=0),e.end<0&&(e.end=0),"<-"==e.dir){const{start:t,end:n}=e;e.start=n,e.end=t}let c=0;C(t,t=>{if(t.nodeType!==Node.TEXT_NODE)return;const n=(t.nodeValue||"").length;if(c+n>=e.start&&(o||(o=t,s=e.start-c),c+n>=e.end))return r=t,i=e.end-c,"stop";c+=n}),o||(o=t),r||(r=t),"<-"==e.dir&&([o,s,r,i]=[r,i,o,s]),n.setBaseAndExtent(o,s,r,i)}function b(){const e=window.getSelection().getRangeAt(0),n=document.createRange();return n.selectNodeContents(t),n.setEnd(e.startContainer,e.startOffset),n.toString()}function w(){const e=window.getSelection().getRangeAt(0),n=document.createRange();return n.selectNodeContents(t),n.setStart(e.endContainer,e.endOffset),n.toString()}function O(){if(!a)return;const e=t.innerHTML,n=y(),o=c[d];if(o&&o.html===e&&o.pos.start===n.start&&o.pos.end===n.end)return;c[++d]={html:e,pos:n},c.splice(d+1);d>300&&(d=300,c.splice(0,1))}function C(t,e){const n=[];t.firstChild&&n.push(t.firstChild);let o=n.pop();for(;o&&"stop"!==e(o);)o.nextSibling&&n.push(o.nextSibling),o.firstChild&&n.push(o.firstChild),o=n.pop()}function k(t){return t.metaKey||t.ctrlKey}function T(t){return k(t)&&!t.shiftKey&&"KeyZ"===t.code}function v(t){return k(t)&&t.shiftKey&&"KeyZ"===t.code}function x(t){t=t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;"),document.execCommand("insertHTML",!1,t)}function E(t,e){let n=0;return(...o)=>{clearTimeout(n),n=window.setTimeout(()=>t(...o),e)}}function S(t){let e=t.length-1;for(;e>=0&&"\n"!==t[e];)e--;let n=++e;for(;n<t.length&&/[ \t]/.test(t[n]);)n++;return[t.substring(e,n)||"",e,n]}function N(){return t.textContent||""}function A(t){t.preventDefault()}return h("keydown",e=>{e.defaultPrevented||(s=N(),function(t){if("Enter"===t.key){const e=b(),n=w();let[r]=S(e),s=r;if(o.indentOn.test(e)&&(s+=o.tab),f?(A(t),x("\n"+s)):s.length>0&&(A(t),x("\n"+s)),s!==r&&"}"===n[0]){const t=y();x("\n"+r),m(t)}}}(e),function(t){if("Tab"===t.key)if(A(t),t.shiftKey){const t=b();let[e,n]=S(t);if(e.length>0){const t=y(),r=Math.min(o.tab.length,e.length);m({start:n,end:n+r}),document.execCommand("delete"),t.start-=r,t.end-=r,m(t)}}else x(o.tab)}(e),function(t){const e="([{'\"",n=")]}'\"",o=w();if(n.includes(t.key)&&o.substr(0,1)===t.key){const e=y();A(t),e.start=++e.end,m(e)}else if(e.includes(t.key)){const o=y();A(t);const r=t.key+n[e.indexOf(t.key)];x(r),o.start=++o.end,m(o)}}(e),function(e){if(T(e)){A(e);const n=c[--d];n&&(t.innerHTML=n.html,m(n.pos)),d<0&&(d=0)}if(v(e)){A(e);const n=c[++d];n&&(t.innerHTML=n.html,m(n.pos)),d>=c.length&&d--}}(e),p(e)&&!u&&(O(),u=!0))}),h("keyup",t=>{t.defaultPrevented||t.isComposing||(s!==N()&&l(),g(t),r&&r(N()))}),h("focus",t=>{a=!0}),h("blur",t=>{a=!1}),h("paste",n=>{O(),function(n){A(n);const o=(n.originalEvent||n).clipboardData.getData("text/plain"),r=y();x(o),e(t),m({start:r.end+o.length,end:r.end+o.length})}(n),O(),r&&r(N())}),{updateOptions(t){t=Object.assign(Object.assign({},t),t)},updateCode(n){t.textContent=n,e(t)},onUpdate(t){r=t},toString:N,destroy(){for(let[e,n]of i)t.removeEventListener(e,n)}}}