UNPKG

quill-uploader

Version:

Quill custom Uploader, supports images, videos, and attachments, with customizable loading indicators.

5 lines 10.6 kB
/*! * Quill Uploader Module v1.1.8 * https://github.com/mudoo/quill-uploader */ !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("Quill")):"function"==typeof define&&define.amd?define(["Quill"],t):"object"==typeof exports?exports.QuillUploader=t(require("Quill")):e.QuillUploader=t(e.Quill)}(self,(e=>(()=>{"use strict";var t=[,t=>{t.exports=e}],i={};function n(e){var o=i[e];if(void 0!==o)return o.exports;var l=i[e]={exports:{}};return t[e](l,l.exports,n),l.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var i in t)n.o(t,i)&&!n.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var o={};n.r(o),n.d(o,{default:()=>w});var l=n(1),s=n.n(l);const r=window.Quill||s(),a=r.import("formats/image"),d=r.import("blots/embed");class c extends d{static create(e){const t=super.create(e);if(!0===e)return t;if("string"==typeof e&&(e={url:e}),e.url){const i=document.createElement("img");i.setAttribute("src",e.url),i.setAttribute("alt",e.label||e.name||""),t.appendChild(i)}const i=Object.assign({},e);return delete i.url,Object.assign(t.dataset,i),t.setAttribute("contenteditable","false"),t}static formats(e){return Object.assign({},e.dataset)}static value(){}static register(){r.import("blots/block").allowedChildren.push(c)}}c.blotName="loadingBlot",c.className="ql-uploading",c.tagName="span",c.allowedChildren=[a];const u=c,h=window.Quill||s(),p=h.import("formats/link");class m extends p{static create(e){"string"==typeof e&&(e={url:e});const t=super.create(e.url);return e.download&&(t.setAttribute("download",e.download),delete e.download),delete e.url,Object.assign(t.dataset,e),t}static formats(e){const t=Object.assign({},e.dataset);return t.url||(t.url=e.getAttribute("href")),t}static register(){h.import("blots/block").allowedChildren.push(m)}format(e,t){t&&"object"==typeof t?super.format(e,t.url):super.format(e,t)}}const g=m;function A(e,t){return t=Object.assign({time:3},t),new Promise(((i,n)=>{let o=document.createElement("video");const l={autoplay:!0,loop:!0,muted:!0,playsinline:!0,"webkit-playsinline":!0,preload:"auto",crossOrigin:"anonymous"};for(const e in l)Object.prototype.hasOwnProperty.call(l,e)&&o.setAttribute(e,String(l[e]));const s=e instanceof File;let r=e;s&&(r=URL.createObjectURL(e)),o.addEventListener("loadedmetadata",(function(){if(!t||!t.time)return;let e=t.time;e<1&&(e=o.duration*e),o.currentTime=e})),o.addEventListener("loadeddata",(function(){const e=function(e,t={quality:.8,type:"image/jpeg"}){const i=Object.assign({quality:.8,type:"image/jpeg"},t),n=document.createElement("canvas");n.width=e.videoWidth,n.height=e.videoHeight;const o=n.getContext("2d");o&&o.drawImage(e,0,0,n.width,n.height);return n.toDataURL(i.type,i.quality)}(o,t),n={thumb:e,duration:Math.round(o.duration),width:o.videoWidth,height:o.videoHeight};s&&URL.revokeObjectURL(r),i(n),o=null})),o.addEventListener("play",(function(){this.pause()})),o.addEventListener("error",(function(e){n(e),o=null})),o.src=r}))}var f=function(e,t,i,n){return new(i||(i=Promise))((function(o,l){function s(e){try{a(n.next(e))}catch(e){l(e)}}function r(e){try{a(n.throw(e))}catch(e){l(e)}}function a(e){var t;e.done?o(e.value):(t=e.value,t instanceof i?t:new i((function(e){e(t)}))).then(s,r)}a((n=n.apply(e,t||[])).next())}))};const y=window.Quill||s();class b{static findType(e,t=b.Accepts){const i=Object.keys(t);return i.includes(e)?e:i.find((i=>t[i].includes(e)))||"attachment"}static register(){y.register(u,!0),y.register(g,!0)}constructor(e,t){this.quill=e,this.quill.customUploader=this,this.options=Object.assign({handler:null,upload:null,accepts:this.constructor.Accepts,imagePreload:!0,focusOnDone:!1},t);const i=Object.keys(this.options.accepts||{}).reduce(((e,t)=>e.concat(this.options.accepts[t])),[]);this.quill.uploader&&this.quill.uploader.options&&(this.quill.uploader.options.mimetypes=i),"function"!=typeof this.options.upload&&console.error("[Missing config] upload function that returns a promise is required");const n=this.quill.getModule("toolbar");n&&Object.keys(this.options.accepts||{}).forEach((e=>{n.addHandler(e,(()=>this.pickFile(e)))})),this.clipboardInit()}clipboardInit(){let e,t=[];const i=()=>{t.forEach((e=>{const t=this.getLoadingDomRange(e.name);this.uploadFiles(t,[e])})),t=[]};this.quill.clipboard.addMatcher(Node.ELEMENT_NODE,((n,o)=>{if("img"===n.nodeName.toLowerCase()&&n.src.startsWith("data:")){const o=function(e,t){const i=e.split(","),n=i[0].match(/:(.*?);/),o=n?n[1]:"image/png",l=atob(i[1]);let s=l.length;const r=new Uint8Array(s);if(!t){const e=o.split("/")[1].replace("jpeg","jpg");t=Math.random().toString().substr(3)+"."+e}for(;s--;)r[s]=l.charCodeAt(s);return new File([r],t,{type:o})}(n.src,"");o.base64=n.src;const r=(new l.Delta).insert({[u.blotName]:{name:o.name,url:o.base64,key:o.name}});return s=o,t.push(s),e&&window.clearTimeout(e),e=window.setTimeout(i,100),r}var s;return o}))}pickFile(e){var t;let i=this.quill.container.querySelector("input.ql-uploader[type=file]");null==i&&(i=document.createElement("input"),i.setAttribute("type","file"),i.classList.add("ql-uploader"),i.setAttribute("style","visibility:hidden"),i.addEventListener("change",(()=>{const e=this.quill.getSelection(!0),t=i.files;null!=t&&0!==t.length&&(this.uploadFiles(e,t),i.value="")})),this.quill.container.appendChild(i));const n=(null===(t=this.options.accepts&&this.options.accepts[e])||void 0===t?void 0:t.join(", "))||"image/*";i.setAttribute("accept",n),i.click()}insertPlaceholder(e,t){const i=e.index;e.index++,this.quill.history.ignoreChange=!0,e.length&&this.quill.deleteText(i,e.length,"api");const n=this.quill.insertEmbed(i,u.blotName,t,"api");return this.quill.history.ignoreChange=!1,n}insertFilePlaceholder(e,t){const i=this.constructor.findType(t.type);t.key||(t.key=function(e=8){const t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";return Array.from({length:e},(()=>t[Math.floor(62*Math.random())])).join("")}());const n=t.key,o=this.getLoadingDomRange(n);return o.delta?Promise.resolve(o.delta):new Promise((o=>{var l,s,r,a;"attachment"===i?o(this.insertPlaceholder(e,{label:t.name,url:this.constructor.DefaultAttachmentPlaceholder,key:n})):t.thumb||t.base64?o(this.insertPlaceholder(e,{name:t.name,url:t.thumb||t.base64,key:n})):(null===(s=null===(l=this.options.accepts)||void 0===l?void 0:l.image)||void 0===s?void 0:s.includes(t.type))?function(e){return new Promise(((t,i)=>{let n=new FileReader;n.onload=function(e){var i;const o=null===(i=e.target)||void 0===i?void 0:i.result;n=null,t(o)},n.onerror=e=>{i(e),n=null},n.readAsDataURL(e)}))}(t).then((i=>{o(this.insertPlaceholder(e,{name:t.name,url:i,key:n}))})):(null===(a=null===(r=this.options.accepts)||void 0===r?void 0:r.video)||void 0===a?void 0:a.includes(t.type))?A(t).then((i=>{o(this.insertPlaceholder(e,{name:t.name,url:i.thumb,key:n}))})):o(this.insertPlaceholder(e,{url:this.constructor.DefaultFilePlaceholder,key:n}))}))}calculatePlaceholderInsertLength(e){return e.ops.reduce(((e,t)=>(Object.prototype.hasOwnProperty.call(t,"insert")&&e++,e)),0)}getLoadingDomRange(e){const t=this.quill.container.querySelector(`.ql-uploading[data-key="${e}"]`);if(!t)return Object.assign({index:0,length:0},this.quill.getSelection());const i=y.find(t),n=this.quill.getIndex(i),o=this.quill.getContents(n,1);return{blot:i,delta:o,index:n,length:this.calculatePlaceholderInsertLength(o)}}loadImage(e){return new Promise((t=>{var i;const n=this.getLoadingDomRange(e.key),o=(null===(i=n.blot)||void 0===i?void 0:i.domNode).querySelector("img");o?(o.addEventListener("load",(()=>t(n))),o.src=e.url):t(n)}))}insertToEditor(e){return f(this,void 0,void 0,(function*(){const t=this.constructor.findType(e.type);"image"===t&&this.options.imagePreload&&(yield this.loadImage(e));const i=this.getLoadingDomRange(e.key);let n=i.length;return this.quill.history.ignoreChange=!0,this.quill.deleteText(i.index,n,"api"),this.quill.history.ignoreChange=!1,"attachment"===t?(n=e.name.length+1,this.quill.insertText(i.index,e.name,{link:Object.assign({key:e.key,download:e.name,url:e.url,ext:e.name.slice(e.name.lastIndexOf(".")+1)},e.delta)},"user"),this.quill.insertText(i.index+n-1," ",{link:null},"user")):this.quill.insertEmbed(i.index,t,e.delta||e.url,"user"),this.quill.setSelection(i.index+n,"silent"),Object.assign(Object.assign({},i),{length:n})}))}removePlaceholder(e){this.quill.history.ignoreChange=!0;const t=this.getLoadingDomRange(e.key);this.quill.deleteText(t.index,t.length,"api"),this.quill.history.ignoreChange=!1}uploadFiles(e,t){return f(this,void 0,void 0,(function*(){let i,n=Array.from(t);if(this.options.handler&&(n=yield this.options.handler(n)),n=n.filter((e=>e&&e.size>0)),!n.length)return;this.quill.emitter.emit(this.constructor.Events.start,n),yield Promise.all(n.map((t=>this.insertFilePlaceholder(e,t))));const o=yield this.options.upload(e,n,((e,t)=>f(this,void 0,void 0,(function*(){e?this.removePlaceholder(t):i=yield this.insertToEditor(t)}))));o?(yield Promise.allSettled(o.map((e=>f(this,void 0,void 0,(function*(){e.url?i=yield this.insertToEditor(e):this.removePlaceholder(e)}))))),this.done(i,o)):this.done(i,o)}))}done(e,t){e&&this.options.focusOnDone&&(this.quill.setSelection(e.index+e.length,"user"),setTimeout((()=>this.quill.focus()),16)),this.quill.emitter.emit(this.constructor.Events.done,t)}}b.DefaultFilePlaceholder="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAC0AQMAAADfKmdSAAAAA1BMVEX19fWwaZ+KAAAAHklEQVRYw+3BMQEAAADCIPuntsYOYAAAAAAAAABhBxzUAAEYBjd2AAAAAElFTkSuQmCC",b.DefaultAttachmentPlaceholder="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYAQMAAADaua+7AAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAAtJREFUCNdjoDEAAABgAAGVQESKAAAAAElFTkSuQmCC",b.Accepts={image:["image/jpeg","image/png","image/gif"],video:["video/mp4"],attachment:["text/plain","application/pdf","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","application/vnd.ms-powerpoint","application/vnd.openxmlformats-officedocument.presentationml.presentation","application/zip","application/x-zip-compressed","application/vnd.rar","application/x-7z-compressed"]},b.Events={start:"uploader-start",done:"uploader-done"};const v=b;window.Quill&&window.Quill.register("modules/customUploader",b);const w=v;return o})()));