@ckeditor/ckeditor5-ckbox 0.0.0-nightly-20231121.0 → 0.0.0-nightly-20231123.0

Sign up to get free protection for your applications and to get access to all the features.
package/build/ckbox.js CHANGED
@@ -2,4 +2,4 @@
2
2
  /*!
3
3
  * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
4
4
  * For licensing, see LICENSE.md.
5
- */(()=>{var e={704:(e,t,i)=>{e.exports=i(79)("./src/core.js")},492:(e,t,i)=>{e.exports=i(79)("./src/engine.js")},273:(e,t,i)=>{e.exports=i(79)("./src/ui.js")},448:(e,t,i)=>{e.exports=i(79)("./src/upload.js")},209:(e,t,i)=>{e.exports=i(79)("./src/utils.js")},79:e=>{"use strict";e.exports=CKEditor5.dll}},t={};function i(o){var r=t[o];if(void 0!==r)return r.exports;var n=t[o]={exports:{}};return e[o](n,n.exports,i),n.exports}i.d=(e,t)=>{for(var o in t)i.o(t,o)&&!i.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var o={};(()=>{"use strict";i.r(o),i.d(o,{CKBox:()=>P,CKBoxEditing:()=>E,CKBoxUI:()=>r});var e=i(704),t=i(273);class r extends e.Plugin{static get pluginName(){return"CKBoxUI"}afterInit(){const e=this.editor,i=e.commands.get("ckbox");if(!i)return;const o=e.t;e.ui.componentFactory.add("ckbox",(r=>{const n=new t.ButtonView(r);return n.set({label:o("Open file manager"),icon:'<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M11.627 16.5zm5.873-.196zm0-7.001V8h-13v8.5h4.341c.191.54.457 1.044.785 1.5H2a1.5 1.5 0 0 1-1.5-1.5v-13A1.5 1.5 0 0 1 2 2h4.5a1.5 1.5 0 0 1 1.06.44L9.122 4H16a1.5 1.5 0 0 1 1.5 1.5v1A1.5 1.5 0 0 1 19 8v2.531a6.027 6.027 0 0 0-1.5-1.228zM16 6.5v-1H8.5l-2-2H2v13h1V8a1.5 1.5 0 0 1 1.5-1.5H16z"/><path d="M14.5 19.5a5 5 0 1 1 0-10 5 5 0 0 1 0 10zM15 14v-2h-1v2h-2v1h2v2h1v-2h2v-1h-2z"/></svg>',tooltip:!0}),n.bind("isOn","isEnabled").to(i,"value","isEnabled"),n.on("execute",(()=>{e.execute("ckbox")})),n}))}}var n=i(492),s=i(209),a=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","#","$","%","*","+",",","-",".",":",";","=","?","@","[","]","^","_","{","|","}","~"],c=e=>{let t=0;for(let i=0;i<e.length;i++){let o=e[i];t=83*t+a.indexOf(o)}return t},l=e=>{let t=e/255;return t<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)},d=e=>{let t=Math.max(0,Math.min(1,e));return t<=.0031308?Math.trunc(12.92*t*255+.5):Math.trunc(255*(1.055*Math.pow(t,.4166666666666667)-.055)+.5)},u=(e,t)=>(e=>e<0?-1:1)(e)*Math.pow(Math.abs(e),t),g=class extends Error{constructor(e){super(e),this.name="ValidationError",this.message=e}},h=e=>{if(!e||e.length<6)throw new g("The blurhash string must be at least 6 characters");let t=c(e[0]),i=Math.floor(t/9)+1,o=t%9+1;if(e.length!==4+2*o*i)throw new g(`blurhash length mismatch: length is ${e.length} but it should be ${4+2*o*i}`)},m=e=>{let t=e>>8&255,i=255&e;return[l(e>>16),l(t),l(i)]},b=(e,t)=>{let i=Math.floor(e/361),o=Math.floor(e/19)%19,r=e%19;return[u((i-9)/9,2)*t,u((o-9)/9,2)*t,u((r-9)/9,2)*t]},p=(e,t,i,o)=>{h(e),o|=1;let r=c(e[0]),n=Math.floor(r/9)+1,s=r%9+1,a=(c(e[1])+1)/166,l=new Array(s*n);for(let t=0;t<l.length;t++)if(0===t){let i=c(e.substring(2,6));l[t]=m(i)}else{let i=c(e.substring(4+2*t,6+2*t));l[t]=b(i,a*o)}let u=4*t,g=new Uint8ClampedArray(u*i);for(let e=0;e<i;e++)for(let o=0;o<t;o++){let r=0,a=0,c=0;for(let d=0;d<n;d++)for(let n=0;n<s;n++){let u=Math.cos(Math.PI*o*n/t)*Math.cos(Math.PI*e*d/i),g=l[n+d*s];r+=g[0]*u,a+=g[1]*u,c+=g[2]*u}let h=d(r),m=d(a),b=d(c);g[4*o+0+e*u]=h,g[4*o+1+e*u]=m,g[4*o+2+e*u]=b,g[4*o+3+e*u]=255}return g};function f(e){const t=[];let i=0;for(const o in e){const r=parseInt(o,10);isNaN(r)||(r>i&&(i=r),t.push(`${e[o]} ${o}w`))}const o=[{srcset:t.join(","),sizes:`(max-width: ${i}px) 100vw, ${i}px`,type:"image/webp"}];return{imageFallbackUrl:e.default,imageSources:o}}const k=32;class x extends e.Command{constructor(e){super(e),this._chosenAssets=new Set,this._wrapper=null,this._initListeners()}refresh(){this.value=this._getValue(),this.isEnabled=this._checkEnabled()}execute(){this.fire("ckbox:open")}_getValue(){return null!==this._wrapper}_checkEnabled(){const e=this.editor.commands.get("insertImage"),t=this.editor.commands.get("link");return!(!e.isEnabled&&!t.isEnabled)}_prepareOptions(){const e=this.editor.config.get("ckbox");return{theme:e.theme,language:e.language,tokenUrl:e.tokenUrl,serviceOrigin:e.serviceOrigin,dialog:{onClose:()=>this.fire("ckbox:close")},assets:{onChoose:e=>this.fire("ckbox:choose",e)}}}_initListeners(){const e=this.editor,t=e.model,i=!e.config.get("ckbox.ignoreDataId");this.on("ckbox",(()=>{this.refresh()}),{priority:"low"}),this.on("ckbox:open",(()=>{this.isEnabled&&!this.value&&(this._wrapper=(0,s.createElement)(document,"div",{class:"ck ckbox-wrapper"}),document.body.appendChild(this._wrapper),window.CKBox.mount(this._wrapper,this._prepareOptions()))})),this.on("ckbox:close",(()=>{this.value&&(this._wrapper.remove(),this._wrapper=null,e.editing.view.focus())})),this.on("ckbox:choose",((o,r)=>{if(!this.isEnabled)return;const n=e.commands.get("insertImage"),s=e.commands.get("link"),a=function({assets:e,isImageAllowed:t,isLinkAllowed:i}){return e.map((e=>function(e){const t=e.data.metadata;if(!t)return!1;return t.width&&t.height}(e)?{id:e.data.id,type:"image",attributes:w(e)}:{id:e.data.id,type:"link",attributes:v(e)})).filter((e=>"image"===e.type?t:i))}({assets:r,isImageAllowed:n.isEnabled,isLinkAllowed:s.isEnabled}),c=a.length;0!==c&&(t.change((e=>{for(const t of a){const o=t===a[c-1],r=1===c;this._insertAsset(t,o,e,r),i&&(setTimeout((()=>this._chosenAssets.delete(t)),1e3),this._chosenAssets.add(t))}})),e.editing.view.focus())})),this.listenTo(e,"destroy",(()=>{this.fire("ckbox:close"),this._chosenAssets.clear()}))}_insertAsset(e,t,i,o){const r=this.editor.model.document.selection;i.removeSelectionAttribute("linkHref"),"image"===e.type?this._insertImage(e):this._insertLink(e,i,o),t||i.setSelection(r.getLastPosition())}_insertImage(e){const t=this.editor,{imageFallbackUrl:i,imageSources:o,imageTextAlternative:r,imageWidth:n,imageHeight:s,imagePlaceholder:a}=e.attributes;t.execute("insertImage",{source:{src:i,sources:o,alt:r,width:n,height:s,...a?{placeholder:a}:null}})}_insertLink(e,t,i){const o=this.editor,r=o.model,n=r.document.selection,{linkName:a,linkHref:c}=e.attributes;if(n.isCollapsed){const e=(0,s.toMap)(n.getAttributes()),l=t.createText(a,e);if(!i){const e=n.getLastPosition(),i=e.parent;"paragraph"===i.name&&i.isEmpty||o.execute("insertParagraph",{position:e});const s=r.insertContent(l);return t.setSelection(s),void o.execute("link",c)}const d=r.insertContent(l);t.setSelection(d)}o.execute("link",c)}}function w(e){const{imageFallbackUrl:t,imageSources:i}=f(e.data.imageUrls),{description:o,width:r,height:n,blurHash:s}=e.data.metadata,a=function(e){if(e)try{const t=`${k}px`,i=document.createElement("canvas");i.setAttribute("width",t),i.setAttribute("height",t);const o=i.getContext("2d");if(!o)return;const r=o.createImageData(k,k),n=p(e,k,k);return r.data.set(n),o.putImageData(r,0,0),i.toDataURL()}catch(e){return}}(s);return{imageFallbackUrl:t,imageSources:i,imageTextAlternative:o||"",imageWidth:r,imageHeight:n,...a?{imagePlaceholder:a}:null}}function v(e){return{linkName:e.data.name,linkHref:I(e)}}function I(e){const t=new URL(e.data.url);return t.searchParams.set("download","true"),t.toString()}var C=i(448);class A extends e.Plugin{static get requires(){return["ImageUploadEditing","ImageUploadProgress",C.FileRepository,E]}static get pluginName(){return"CKBoxUploadAdapter"}async afterInit(){const e=this.editor,t=!!e.config.get("ckbox"),i=!!window.CKBox;if(!t&&!i)return;const o=e.plugins.get(C.FileRepository),r=e.plugins.get(E);o.createUploadAdapter=t=>new y(t,r.getToken(),e);const n=!e.config.get("ckbox.ignoreDataId"),s=e.plugins.get("ImageUploadEditing");n&&s.on("uploadComplete",((t,{imageElement:i,data:o})=>{e.model.change((e=>{e.setAttribute("ckboxImageId",o.ckboxImageId,i)}))}))}}class y{constructor(e,t,i){this.loader=e,this.token=t,this.editor=i,this.controller=new AbortController,this.serviceOrigin=i.config.get("ckbox.serviceOrigin")}getWorkspaceId(){const e=(0,this.editor.t)("Cannot access default workspace."),t=this.editor.config.get("ckbox.defaultUploadWorkspaceId"),i=function(e,t){const[,i]=e.value.split("."),o=JSON.parse(atob(i)),r=o.auth&&o.auth.ckbox&&o.auth.ckbox.workspaces||[o.aud];return t?"superadmin"==(o.auth&&o.auth.ckbox&&o.auth.ckbox.role)||r.includes(t)?t:null:r[0]}(this.token,t);if(null==i)throw(0,s.logError)("ckbox-access-default-workspace-error"),e;return i}async getAvailableCategories(e=0){const t=new URL("categories",this.serviceOrigin);return t.searchParams.set("limit",50..toString()),t.searchParams.set("offset",e.toString()),t.searchParams.set("workspaceId",this.getWorkspaceId()),this._sendHttpRequest({url:t}).then((async t=>{if(t.totalCount-(e+50)>0){const i=await this.getAvailableCategories(e+50);return[...t.items,...i]}return t.items})).catch((()=>{this.controller.signal.throwIfAborted(),(0,s.logError)("ckbox-fetch-category-http-error")}))}async getCategoryIdForFile(e){const t=function(e){const t=/\.(?<ext>[^.]+)$/;return e.match(t).groups.ext.toLowerCase()}(e.name),i=await this.getAvailableCategories();if(!i)return null;const o=this.editor.config.get("ckbox.defaultUploadCategories");if(o){const e=Object.keys(o).find((e=>o[e].find((e=>e.toLowerCase()==t))));if(e){const t=i.find((t=>t.id===e||t.name===e));return t?t.id:null}}const r=i.find((e=>e.extensions.find((e=>e.toLowerCase()==t))));return r?r.id:null}async upload(){const e=this.editor.t,t=e("Cannot determine a category for the uploaded file."),i=await this.loader.file,o=await this.getCategoryIdForFile(i);if(!o)return Promise.reject(t);const r=new URL("assets",this.serviceOrigin),n=new FormData;r.searchParams.set("workspaceId",this.getWorkspaceId()),n.append("categoryId",o),n.append("file",i);const s={method:"POST",url:r,data:n,onUploadProgress:e=>{e.lengthComputable&&(this.loader.uploadTotal=e.total,this.loader.uploaded=e.loaded)}};return this._sendHttpRequest(s).then((async e=>{const t=f(e.imageUrls);return{ckboxImageId:e.id,default:t.imageFallbackUrl,sources:t.imageSources}})).catch((()=>{const t=e("Cannot upload file:")+` ${i.name}.`;return Promise.reject(t)}))}abort(){this.controller.abort()}_sendHttpRequest({url:e,method:t="GET",data:i,onUploadProgress:o}){const r=this.controller.signal,n=new XMLHttpRequest;n.open(t,e.toString(),!0),n.setRequestHeader("Authorization",this.token.value),n.setRequestHeader("CKBox-Version","CKEditor 5"),n.responseType="json";const s=()=>{n.abort()};return new Promise(((e,t)=>{r.addEventListener("abort",s),n.addEventListener("loadstart",(()=>{r.addEventListener("abort",s)})),n.addEventListener("loadend",(()=>{r.removeEventListener("abort",s)})),n.addEventListener("error",(()=>{t()})),n.addEventListener("abort",(()=>{t()})),n.addEventListener("load",(async()=>{const i=n.response;return!i||i.statusCode>=400?t(i&&i.message):e(i)})),o&&n.upload.addEventListener("progress",(e=>{o(e)})),n.send(i)}))}}class E extends e.Plugin{static get pluginName(){return"CKBoxEditing"}static get requires(){return["CloudServices","LinkEditing","PictureEditing",A]}async init(){const e=this.editor,t=!!e.config.get("ckbox"),i=!!window.CKBox;if(!t&&!i)return;this._initConfig();const o=e.plugins.get("CloudServicesCore"),r=e.config.get("ckbox.tokenUrl");if(r===e.config.get("cloudServices.tokenUrl")){const t=e.plugins.get("CloudServices");this._token=t.token}else this._token=await o.createToken(r).init();e.config.get("ckbox.ignoreDataId")||(this._initSchema(),this._initConversion(),this._initFixers()),i&&e.commands.add("ckbox",new x(e))}getToken(){return this._token}_initConfig(){const e=this.editor;e.config.define("ckbox",{serviceOrigin:"https://api.ckbox.io",defaultUploadCategories:null,ignoreDataId:!1,language:e.locale.uiLanguage,theme:"lark",tokenUrl:e.config.get("cloudServices.tokenUrl")});if(!e.config.get("ckbox.tokenUrl"))throw new s.CKEditorError("ckbox-plugin-missing-token-url",this);e.plugins.has("ImageBlockEditing")||e.plugins.has("ImageInlineEditing")||(0,s.logError)("ckbox-plugin-image-feature-missing",e)}_initSchema(){const e=this.editor.model.schema;e.extend("$text",{allowAttributes:"ckboxLinkId"}),e.isRegistered("imageBlock")&&e.extend("imageBlock",{allowAttributes:["ckboxImageId","ckboxLinkId"]}),e.isRegistered("imageInline")&&e.extend("imageInline",{allowAttributes:["ckboxImageId","ckboxLinkId"]}),e.addAttributeCheck(((e,t)=>{if(!!!e.last.getAttribute("linkHref")&&"ckboxLinkId"===t)return!1}))}_initConversion(){const e=this.editor;e.conversion.for("downcast").add((e=>{e.on("attribute:ckboxLinkId:imageBlock",((e,t,i)=>{const{writer:o,mapper:r,consumable:n}=i;if(!n.consume(t.item,e.name))return;const s=[...r.toViewElement(t.item).getChildren()].find((e=>"a"===e.name));s&&(t.item.hasAttribute("ckboxLinkId")?o.setAttribute("data-ckbox-resource-id",t.item.getAttribute("ckboxLinkId"),s):o.removeAttribute("data-ckbox-resource-id",s))}),{priority:"low"}),e.on("attribute:ckboxLinkId",((e,t,i)=>{const{writer:o,mapper:r,consumable:n}=i;if(n.consume(t.item,e.name)){if(t.attributeOldValue){const e=_(o,t.attributeOldValue);o.unwrap(r.toViewRange(t.range),e)}if(t.attributeNewValue){const e=_(o,t.attributeNewValue);if(t.item.is("selection")){const t=o.document.selection;o.wrap(t.getFirstRange(),e)}else o.wrap(r.toViewRange(t.range),e)}}}),{priority:"low"})})),e.conversion.for("upcast").add((e=>{e.on("element:a",((e,t,i)=>{const{writer:o,consumable:r}=i;if(!t.viewItem.getAttribute("href"))return;if(!r.consume(t.viewItem,{attributes:["data-ckbox-resource-id"]}))return;const n=t.viewItem.getAttribute("data-ckbox-resource-id");if(n)if(t.modelRange)for(let e of t.modelRange.getItems())e.is("$textProxy")&&(e=e.textNode),S(e)&&o.setAttribute("ckboxLinkId",n,e);else{const e=t.modelCursor.nodeBefore||t.modelCursor.parent;o.setAttribute("ckboxLinkId",n,e)}}),{priority:"low"})})),e.conversion.for("downcast").attributeToAttribute({model:"ckboxImageId",view:"data-ckbox-resource-id"}),e.conversion.for("upcast").elementToAttribute({model:{key:"ckboxImageId",value:e=>e.getAttribute("data-ckbox-resource-id")},view:{attributes:{"data-ckbox-resource-id":/[\s\S]+/}}});const t=e.commands.get("replaceImageSource");t&&this.listenTo(t,"cleanupImage",((e,[t,i])=>{t.removeAttribute("ckboxImageId",i)}))}_initFixers(){const e=this.editor,t=e.model,i=t.document.selection;t.document.registerPostFixer(function(e){return t=>{let i=!1;const o=e.model,r=e.commands.get("ckbox");if(!r)return i;for(const e of o.document.differ.getChanges()){if("insert"!==e.type&&"attribute"!==e.type)continue;const o="insert"===e.type?new n.Range(e.position,e.position.getShiftedBy(e.length)):e.range,s="attribute"===e.type&&"linkHref"===e.attributeKey&&null===e.attributeNewValue;for(const e of o.getItems()){if(s&&e.hasAttribute("ckboxLinkId")){t.removeAttribute("ckboxLinkId",e),i=!0;continue}const o=L(e,r._chosenAssets);for(const r of o){const o="image"===r.type?"ckboxImageId":"ckboxLinkId";r.id!==e.getAttribute(o)&&(t.setAttribute(o,r.id,e),i=!0)}}}return i}}(e)),t.document.registerPostFixer(function(e){return t=>!(e.hasAttribute("linkHref")||!e.hasAttribute("ckboxLinkId"))&&(t.removeSelectionAttribute("ckboxLinkId"),!0)}(i))}}function L(e,t){const i=e.is("element","imageInline")||e.is("element","imageBlock"),o=e.hasAttribute("linkHref");return[...t].filter((t=>"image"===t.type&&i?t.attributes.imageFallbackUrl===e.getAttribute("src"):"link"===t.type&&o?t.attributes.linkHref===e.getAttribute("linkHref"):void 0))}function _(e,t){const i=e.createAttributeElement("a",{"data-ckbox-resource-id":t},{priority:5});return e.setCustomProperty("link",!0,i),i}function S(e){return!!e.is("$text")||!(!e.is("element","imageInline")&&!e.is("element","imageBlock"))}class P extends e.Plugin{static get pluginName(){return"CKBox"}static get requires(){return[E,r]}}})(),(window.CKEditor5=window.CKEditor5||{}).ckbox=o})();
5
+ */(()=>{var e={70:(e,t,n)=>{"use strict";n.d(t,{Z:()=>i});var r=n(609),o=n.n(r)()((function(e){return e[1]}));o.push([e.id,':root{--ck-image-processing-highlight-color:#f9fafa;--ck-image-processing-background-color:#e3e5e8}.ck.ck-editor__editable .image.image-processing{position:relative}.ck.ck-editor__editable .image.image-processing:before{animation:ck-image-processing-animation 2s linear infinite;background:linear-gradient(90deg,var(--ck-image-processing-background-color),var(--ck-image-processing-highlight-color),var(--ck-image-processing-background-color));background-size:200% 100%;content:"";height:100%;left:0;position:absolute;top:0;width:100%;z-index:1}.ck.ck-editor__editable .image.image-processing img{height:100%}@keyframes ck-image-processing-animation{0%{background-position:200% 0}to{background-position:-200% 0}}',""]);const i=o},609:e=>{"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=e(t);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n})).join("")},t.i=function(e,n,r){"string"==typeof e&&(e=[[null,e,""]]);var o={};if(r)for(var i=0;i<this.length;i++){var s=this[i][0];null!=s&&(o[s]=!0)}for(var a=0;a<e.length;a++){var c=[].concat(e[a]);r&&o[c[0]]||(n&&(c[2]?c[2]="".concat(n," and ").concat(c[2]):c[2]=n),t.push(c))}},t}},62:(e,t,n)=>{"use strict";var r,o=function(){return void 0===r&&(r=Boolean(window&&document&&document.all&&!window.atob)),r},i=function(){var e={};return function(t){if(void 0===e[t]){var n=document.querySelector(t);if(window.HTMLIFrameElement&&n instanceof window.HTMLIFrameElement)try{n=n.contentDocument.head}catch(e){n=null}e[t]=n}return e[t]}}(),s=[];function a(e){for(var t=-1,n=0;n<s.length;n++)if(s[n].identifier===e){t=n;break}return t}function c(e,t){for(var n={},r=[],o=0;o<e.length;o++){var i=e[o],c=t.base?i[0]+t.base:i[0],l=n[c]||0,u="".concat(c," ").concat(l);n[c]=l+1;var d=a(u),g={css:i[1],media:i[2],sourceMap:i[3]};-1!==d?(s[d].references++,s[d].updater(g)):s.push({identifier:u,updater:m(g,t),references:1}),r.push(u)}return r}function l(e){var t=document.createElement("style"),r=e.attributes||{};if(void 0===r.nonce){var o=n.nc;o&&(r.nonce=o)}if(Object.keys(r).forEach((function(e){t.setAttribute(e,r[e])})),"function"==typeof e.insert)e.insert(t);else{var s=i(e.insert||"head");if(!s)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");s.appendChild(t)}return t}var u,d=(u=[],function(e,t){return u[e]=t,u.filter(Boolean).join("\n")});function g(e,t,n,r){var o=n?"":r.media?"@media ".concat(r.media," {").concat(r.css,"}"):r.css;if(e.styleSheet)e.styleSheet.cssText=d(t,o);else{var i=document.createTextNode(o),s=e.childNodes;s[t]&&e.removeChild(s[t]),s.length?e.insertBefore(i,s[t]):e.appendChild(i)}}function h(e,t,n){var r=n.css,o=n.media,i=n.sourceMap;if(o?e.setAttribute("media",o):e.removeAttribute("media"),i&&"undefined"!=typeof btoa&&(r+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(i))))," */")),e.styleSheet)e.styleSheet.cssText=r;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(r))}}var p=null,f=0;function m(e,t){var n,r,o;if(t.singleton){var i=f++;n=p||(p=l(t)),r=g.bind(null,n,i,!1),o=g.bind(null,n,i,!0)}else n=l(t),r=h.bind(null,n,t),o=function(){!function(e){if(null===e.parentNode)return!1;e.parentNode.removeChild(e)}(n)};return r(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;r(e=t)}else o()}}e.exports=function(e,t){(t=t||{}).singleton||"boolean"==typeof t.singleton||(t.singleton=o());var n=c(e=e||[],t);return function(e){if(e=e||[],"[object Array]"===Object.prototype.toString.call(e)){for(var r=0;r<n.length;r++){var o=a(n[r]);s[o].references--}for(var i=c(e,t),l=0;l<n.length;l++){var u=a(n[l]);0===s[u].references&&(s[u].updater(),s.splice(u,1))}n=i}}}},704:(e,t,n)=>{e.exports=n(79)("./src/core.js")},492:(e,t,n)=>{e.exports=n(79)("./src/engine.js")},273:(e,t,n)=>{e.exports=n(79)("./src/ui.js")},448:(e,t,n)=>{e.exports=n(79)("./src/upload.js")},209:(e,t,n)=>{e.exports=n(79)("./src/utils.js")},79:e=>{"use strict";e.exports=CKEditor5.dll}},t={};function n(r){var o=t[r];if(void 0!==o)return o.exports;var i=t[r]={id:r,exports:{}};return e[r](i,i.exports,n),i.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 r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},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})},n.nc=void 0;var r={};(()=>{"use strict";n.r(r),n.d(r,{CKBox:()=>P,CKBoxEditing:()=>E,CKBoxImageEdit:()=>jn,CKBoxImageEditEditing:()=>_n,CKBoxImageEditUI:()=>kn,CKBoxUI:()=>o});var e=n(704),t=n(273);class o extends e.Plugin{static get pluginName(){return"CKBoxUI"}afterInit(){const e=this.editor,n=e.commands.get("ckbox");if(!n)return;const r=e.t;e.ui.componentFactory.add("ckbox",(o=>{const i=new t.ButtonView(o);return i.set({label:r("Open file manager"),icon:'<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M11.627 16.5zm5.873-.196zm0-7.001V8h-13v8.5h4.341c.191.54.457 1.044.785 1.5H2a1.5 1.5 0 0 1-1.5-1.5v-13A1.5 1.5 0 0 1 2 2h4.5a1.5 1.5 0 0 1 1.06.44L9.122 4H16a1.5 1.5 0 0 1 1.5 1.5v1A1.5 1.5 0 0 1 19 8v2.531a6.027 6.027 0 0 0-1.5-1.228zM16 6.5v-1H8.5l-2-2H2v13h1V8a1.5 1.5 0 0 1 1.5-1.5H16z"/><path d="M14.5 19.5a5 5 0 1 1 0-10 5 5 0 0 1 0 10zM15 14v-2h-1v2h-2v1h2v2h1v-2h2v-1h-2z"/></svg>',tooltip:!0}),i.bind("isOn","isEnabled").to(n,"value","isEnabled"),i.on("execute",(()=>{e.execute("ckbox")})),i}))}}var i=n(492),s=n(209),a=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","#","$","%","*","+",",","-",".",":",";","=","?","@","[","]","^","_","{","|","}","~"],c=e=>{let t=0;for(let n=0;n<e.length;n++){let r=e[n];t=83*t+a.indexOf(r)}return t},l=e=>{let t=e/255;return t<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)},u=e=>{let t=Math.max(0,Math.min(1,e));return t<=.0031308?Math.trunc(12.92*t*255+.5):Math.trunc(255*(1.055*Math.pow(t,.4166666666666667)-.055)+.5)},d=(e,t)=>(e=>e<0?-1:1)(e)*Math.pow(Math.abs(e),t),g=class extends Error{constructor(e){super(e),this.name="ValidationError",this.message=e}},h=e=>{if(!e||e.length<6)throw new g("The blurhash string must be at least 6 characters");let t=c(e[0]),n=Math.floor(t/9)+1,r=t%9+1;if(e.length!==4+2*r*n)throw new g(`blurhash length mismatch: length is ${e.length} but it should be ${4+2*r*n}`)},p=e=>{let t=e>>8&255,n=255&e;return[l(e>>16),l(t),l(n)]},f=(e,t)=>{let n=Math.floor(e/361),r=Math.floor(e/19)%19,o=e%19;return[d((n-9)/9,2)*t,d((r-9)/9,2)*t,d((o-9)/9,2)*t]},m=(e,t,n,r)=>{h(e),r|=1;let o=c(e[0]),i=Math.floor(o/9)+1,s=o%9+1,a=(c(e[1])+1)/166,l=new Array(s*i);for(let t=0;t<l.length;t++)if(0===t){let n=c(e.substring(2,6));l[t]=p(n)}else{let n=c(e.substring(4+2*t,6+2*t));l[t]=f(n,a*r)}let d=4*t,g=new Uint8ClampedArray(d*n);for(let e=0;e<n;e++)for(let r=0;r<t;r++){let o=0,a=0,c=0;for(let u=0;u<i;u++)for(let i=0;i<s;i++){let d=Math.cos(Math.PI*r*i/t)*Math.cos(Math.PI*e*u/n),g=l[i+u*s];o+=g[0]*d,a+=g[1]*d,c+=g[2]*d}let h=u(o),p=u(a),f=u(c);g[4*r+0+e*d]=h,g[4*r+1+e*d]=p,g[4*r+2+e*d]=f,g[4*r+3+e*d]=255}return g};function b(e){const t=[];let n=0;for(const r in e){const o=parseInt(r,10);isNaN(o)||(o>n&&(n=o),t.push(`${e[r]} ${r}w`))}const r=[{srcset:t.join(","),sizes:`(max-width: ${n}px) 100vw, ${n}px`,type:"image/webp"}];return{imageFallbackUrl:e.default,imageSources:r}}const v=32;function _({url:e,method:t="GET",data:n,onUploadProgress:r,signal:o,authorization:i}){const s=new XMLHttpRequest;s.open(t,e.toString()),s.setRequestHeader("Authorization",i),s.setRequestHeader("CKBox-Version","CKEditor 5"),s.responseType="json";const a=()=>{s.abort()};return new Promise(((e,t)=>{o.throwIfAborted(),o.addEventListener("abort",a),s.addEventListener("loadstart",(()=>{o.addEventListener("abort",a)})),s.addEventListener("loadend",(()=>{o.removeEventListener("abort",a)})),s.addEventListener("error",(()=>{t()})),s.addEventListener("abort",(()=>{t()})),s.addEventListener("load",(()=>{const n=s.response;if(!n||n.statusCode>=400)return t(n&&n.message);e(n)})),r&&s.upload.addEventListener("progress",(e=>{r(e)})),s.send(n)}))}class k extends e.Command{constructor(e){super(e),this._chosenAssets=new Set,this._wrapper=null,this._initListeners()}refresh(){this.value=this._getValue(),this.isEnabled=this._checkEnabled()}execute(){this.fire("ckbox:open")}_getValue(){return null!==this._wrapper}_checkEnabled(){const e=this.editor.commands.get("insertImage"),t=this.editor.commands.get("link");return!(!e.isEnabled&&!t.isEnabled)}_prepareOptions(){const e=this.editor.config.get("ckbox");return{theme:e.theme,language:e.language,tokenUrl:e.tokenUrl,serviceOrigin:e.serviceOrigin,dialog:{onClose:()=>this.fire("ckbox:close")},assets:{onChoose:e=>this.fire("ckbox:choose",e)}}}_initListeners(){const e=this.editor,t=e.model,n=!e.config.get("ckbox.ignoreDataId");this.on("ckbox",(()=>{this.refresh()}),{priority:"low"}),this.on("ckbox:open",(()=>{this.isEnabled&&!this.value&&(this._wrapper=(0,s.createElement)(document,"div",{class:"ck ckbox-wrapper"}),document.body.appendChild(this._wrapper),window.CKBox.mount(this._wrapper,this._prepareOptions()))})),this.on("ckbox:close",(()=>{this.value&&(this._wrapper.remove(),this._wrapper=null,e.editing.view.focus())})),this.on("ckbox:choose",((r,o)=>{if(!this.isEnabled)return;const i=e.commands.get("insertImage"),s=e.commands.get("link"),a=function({assets:e,isImageAllowed:t,isLinkAllowed:n}){return e.map((e=>function(e){const t=e.data.metadata;if(!t)return!1;return t.width&&t.height}(e)?{id:e.data.id,type:"image",attributes:y(e)}:{id:e.data.id,type:"link",attributes:w(e)})).filter((e=>"image"===e.type?t:n))}({assets:o,isImageAllowed:i.isEnabled,isLinkAllowed:s.isEnabled}),c=a.length;0!==c&&(t.change((e=>{for(const t of a){const r=t===a[c-1],o=1===c;this._insertAsset(t,r,e,o),n&&(setTimeout((()=>this._chosenAssets.delete(t)),1e3),this._chosenAssets.add(t))}})),e.editing.view.focus())})),this.listenTo(e,"destroy",(()=>{this.fire("ckbox:close"),this._chosenAssets.clear()}))}_insertAsset(e,t,n,r){const o=this.editor.model.document.selection;n.removeSelectionAttribute("linkHref"),"image"===e.type?this._insertImage(e):this._insertLink(e,n,r),t||n.setSelection(o.getLastPosition())}_insertImage(e){const t=this.editor,{imageFallbackUrl:n,imageSources:r,imageTextAlternative:o,imageWidth:i,imageHeight:s,imagePlaceholder:a}=e.attributes;t.execute("insertImage",{source:{src:n,sources:r,alt:o,width:i,height:s,...a?{placeholder:a}:null}})}_insertLink(e,t,n){const r=this.editor,o=r.model,i=o.document.selection,{linkName:a,linkHref:c}=e.attributes;if(i.isCollapsed){const e=(0,s.toMap)(i.getAttributes()),l=t.createText(a,e);if(!n){const e=i.getLastPosition(),n=e.parent;"paragraph"===n.name&&n.isEmpty||r.execute("insertParagraph",{position:e});const s=o.insertContent(l);return t.setSelection(s),void r.execute("link",c)}const u=o.insertContent(l);t.setSelection(u)}r.execute("link",c)}}function y(e){const{imageFallbackUrl:t,imageSources:n}=b(e.data.imageUrls),{description:r,width:o,height:i,blurHash:s}=e.data.metadata,a=function(e){if(e)try{const t=`${v}px`,n=document.createElement("canvas");n.setAttribute("width",t),n.setAttribute("height",t);const r=n.getContext("2d");if(!r)return;const o=r.createImageData(v,v),i=m(e,v,v);return o.data.set(i),r.putImageData(o,0,0),n.toDataURL()}catch(e){return}}(s);return{imageFallbackUrl:t,imageSources:n,imageTextAlternative:r||"",imageWidth:o,imageHeight:i,...a?{imagePlaceholder:a}:null}}function w(e){return{linkName:e.data.name,linkHref:x(e)}}function x(e){const t=new URL(e.data.url);return t.searchParams.set("download","true"),t.toString()}var I=n(448);class j extends e.Plugin{static get requires(){return["ImageUploadEditing","ImageUploadProgress",I.FileRepository,E]}static get pluginName(){return"CKBoxUploadAdapter"}async afterInit(){const e=this.editor,t=!!e.config.get("ckbox"),n=!!window.CKBox;if(!t&&!n)return;const r=e.plugins.get(I.FileRepository),o=e.plugins.get(E);r.createUploadAdapter=t=>new A(t,o.getToken(),e);const i=!e.config.get("ckbox.ignoreDataId"),s=e.plugins.get("ImageUploadEditing");i&&s.on("uploadComplete",((t,{imageElement:n,data:r})=>{e.model.change((e=>{e.setAttribute("ckboxImageId",r.ckboxImageId,n)}))}))}}class A{constructor(e,t,n){this.loader=e,this.token=t,this.editor=n,this.controller=new AbortController,this.serviceOrigin=n.config.get("ckbox.serviceOrigin")}getWorkspaceId(){const e=(0,this.editor.t)("Cannot access default workspace."),t=this.editor.config.get("ckbox.defaultUploadWorkspaceId"),n=function(e,t){const[,n]=e.value.split("."),r=JSON.parse(atob(n)),o=r.auth&&r.auth.ckbox&&r.auth.ckbox.workspaces||[r.aud];return t?"superadmin"==(r.auth&&r.auth.ckbox&&r.auth.ckbox.role)||o.includes(t)?t:null:o[0]}(this.token,t);if(null==n)throw(0,s.logError)("ckbox-access-default-workspace-error"),e;return n}async getAvailableCategories(e=0){const t=new URL("categories",this.serviceOrigin);return t.searchParams.set("limit",50..toString()),t.searchParams.set("offset",e.toString()),t.searchParams.set("workspaceId",this.getWorkspaceId()),_({url:t,signal:this.controller.signal,authorization:this.token.value}).then((async t=>{if(t.totalCount-(e+50)>0){const n=await this.getAvailableCategories(e+50);return[...t.items,...n]}return t.items})).catch((()=>{this.controller.signal.throwIfAborted(),(0,s.logError)("ckbox-fetch-category-http-error")}))}async getCategoryIdForFile(e){const t=function(e){const t=/\.(?<ext>[^.]+)$/;return e.match(t).groups.ext.toLowerCase()}(e.name),n=await this.getAvailableCategories();if(!n)return null;const r=this.editor.config.get("ckbox.defaultUploadCategories");if(r){const e=Object.keys(r).find((e=>r[e].find((e=>e.toLowerCase()==t))));if(e){const t=n.find((t=>t.id===e||t.name===e));return t?t.id:null}}const o=n.find((e=>e.extensions.find((e=>e.toLowerCase()==t))));return o?o.id:null}async upload(){const e=this.editor.t,t=e("Cannot determine a category for the uploaded file."),n=await this.loader.file,r=await this.getCategoryIdForFile(n);if(!r)return Promise.reject(t);const o=new URL("assets",this.serviceOrigin),i=new FormData;o.searchParams.set("workspaceId",this.getWorkspaceId()),i.append("categoryId",r),i.append("file",n);return _({method:"POST",url:o,data:i,onUploadProgress:e=>{e.lengthComputable&&(this.loader.uploadTotal=e.total,this.loader.uploaded=e.loaded)},signal:this.controller.signal,authorization:this.token.value}).then((async e=>{const t=b(e.imageUrls);return{ckboxImageId:e.id,default:t.imageFallbackUrl,sources:t.imageSources}})).catch((()=>{const t=e("Cannot upload file:")+` ${n.name}.`;return Promise.reject(t)}))}abort(){this.controller.abort()}}class E extends e.Plugin{static get pluginName(){return"CKBoxEditing"}static get requires(){return["CloudServices","LinkEditing","PictureEditing",j]}async init(){const e=this.editor,t=!!e.config.get("ckbox"),n=!!window.CKBox;if(!t&&!n)return;this._initConfig();const r=e.plugins.get("CloudServicesCore"),o=e.config.get("ckbox.tokenUrl");if(o===e.config.get("cloudServices.tokenUrl")){const t=e.plugins.get("CloudServices");this._token=t.token}else this._token=await r.createToken(o).init();e.config.get("ckbox.ignoreDataId")||(this._initSchema(),this._initConversion(),this._initFixers()),n&&e.commands.add("ckbox",new k(e))}getToken(){return this._token}_initConfig(){const e=this.editor;e.config.define("ckbox",{serviceOrigin:"https://api.ckbox.io",defaultUploadCategories:null,ignoreDataId:!1,language:e.locale.uiLanguage,theme:"lark",tokenUrl:e.config.get("cloudServices.tokenUrl")});if(!e.config.get("ckbox.tokenUrl"))throw new s.CKEditorError("ckbox-plugin-missing-token-url",this);e.plugins.has("ImageBlockEditing")||e.plugins.has("ImageInlineEditing")||(0,s.logError)("ckbox-plugin-image-feature-missing",e)}_initSchema(){const e=this.editor.model.schema;e.extend("$text",{allowAttributes:"ckboxLinkId"}),e.isRegistered("imageBlock")&&e.extend("imageBlock",{allowAttributes:["ckboxImageId","ckboxLinkId"]}),e.isRegistered("imageInline")&&e.extend("imageInline",{allowAttributes:["ckboxImageId","ckboxLinkId"]}),e.addAttributeCheck(((e,t)=>{if(!!!e.last.getAttribute("linkHref")&&"ckboxLinkId"===t)return!1}))}_initConversion(){const e=this.editor;e.conversion.for("downcast").add((e=>{e.on("attribute:ckboxLinkId:imageBlock",((e,t,n)=>{const{writer:r,mapper:o,consumable:i}=n;if(!i.consume(t.item,e.name))return;const s=[...o.toViewElement(t.item).getChildren()].find((e=>"a"===e.name));s&&(t.item.hasAttribute("ckboxLinkId")?r.setAttribute("data-ckbox-resource-id",t.item.getAttribute("ckboxLinkId"),s):r.removeAttribute("data-ckbox-resource-id",s))}),{priority:"low"}),e.on("attribute:ckboxLinkId",((e,t,n)=>{const{writer:r,mapper:o,consumable:i}=n;if(i.consume(t.item,e.name)){if(t.attributeOldValue){const e=S(r,t.attributeOldValue);r.unwrap(o.toViewRange(t.range),e)}if(t.attributeNewValue){const e=S(r,t.attributeNewValue);if(t.item.is("selection")){const t=r.document.selection;r.wrap(t.getFirstRange(),e)}else r.wrap(o.toViewRange(t.range),e)}}}),{priority:"low"})})),e.conversion.for("upcast").add((e=>{e.on("element:a",((e,t,n)=>{const{writer:r,consumable:o}=n;if(!t.viewItem.getAttribute("href"))return;if(!o.consume(t.viewItem,{attributes:["data-ckbox-resource-id"]}))return;const i=t.viewItem.getAttribute("data-ckbox-resource-id");if(i)if(t.modelRange)for(let e of t.modelRange.getItems())e.is("$textProxy")&&(e=e.textNode),O(e)&&r.setAttribute("ckboxLinkId",i,e);else{const e=t.modelCursor.nodeBefore||t.modelCursor.parent;r.setAttribute("ckboxLinkId",i,e)}}),{priority:"low"})})),e.conversion.for("downcast").attributeToAttribute({model:"ckboxImageId",view:"data-ckbox-resource-id"}),e.conversion.for("upcast").elementToAttribute({model:{key:"ckboxImageId",value:e=>e.getAttribute("data-ckbox-resource-id")},view:{attributes:{"data-ckbox-resource-id":/[\s\S]+/}}});const t=e.commands.get("replaceImageSource");t&&this.listenTo(t,"cleanupImage",((e,[t,n])=>{t.removeAttribute("ckboxImageId",n)}))}_initFixers(){const e=this.editor,t=e.model,n=t.document.selection;t.document.registerPostFixer(function(e){return t=>{let n=!1;const r=e.model,o=e.commands.get("ckbox");if(!o)return n;for(const e of r.document.differ.getChanges()){if("insert"!==e.type&&"attribute"!==e.type)continue;const r="insert"===e.type?new i.Range(e.position,e.position.getShiftedBy(e.length)):e.range,s="attribute"===e.type&&"linkHref"===e.attributeKey&&null===e.attributeNewValue;for(const e of r.getItems()){if(s&&e.hasAttribute("ckboxLinkId")){t.removeAttribute("ckboxLinkId",e),n=!0;continue}const r=C(e,o._chosenAssets);for(const o of r){const r="image"===o.type?"ckboxImageId":"ckboxLinkId";o.id!==e.getAttribute(r)&&(t.setAttribute(r,o.id,e),n=!0)}}}return n}}(e)),t.document.registerPostFixer(function(e){return t=>!(e.hasAttribute("linkHref")||!e.hasAttribute("ckboxLinkId"))&&(t.removeSelectionAttribute("ckboxLinkId"),!0)}(n))}}function C(e,t){const n=e.is("element","imageInline")||e.is("element","imageBlock"),r=e.hasAttribute("linkHref");return[...t].filter((t=>"image"===t.type&&n?t.attributes.imageFallbackUrl===e.getAttribute("src"):"link"===t.type&&r?t.attributes.linkHref===e.getAttribute("linkHref"):void 0))}function S(e,t){const n=e.createAttributeElement("a",{"data-ckbox-resource-id":t},{priority:5});return e.setCustomProperty("link",!0,n),n}function O(e){return!!e.is("$text")||!(!e.is("element","imageInline")&&!e.is("element","imageBlock"))}class P extends e.Plugin{static get pluginName(){return"CKBox"}static get requires(){return[E,o]}}const L=function(){this.__data__=[],this.size=0};const U=function(e,t){return e===t||e!=e&&t!=t};const T=function(e,t){for(var n=e.length;n--;)if(U(e[n][0],t))return n;return-1};var M=Array.prototype.splice;const B=function(e){var t=this.__data__,n=T(t,e);return!(n<0)&&(n==t.length-1?t.pop():M.call(t,n,1),--this.size,!0)};const z=function(e){var t=this.__data__,n=T(t,e);return n<0?void 0:t[n][1]};const F=function(e){return T(this.__data__,e)>-1};const N=function(e,t){var n=this.__data__,r=T(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this};function K(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}K.prototype.clear=L,K.prototype.delete=B,K.prototype.get=z,K.prototype.has=F,K.prototype.set=N;const R=K;const V=function(){this.__data__=new R,this.size=0};const H=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n};const $=function(e){return this.__data__.get(e)};const D=function(e){return this.__data__.has(e)};const q="object"==typeof global&&global&&global.Object===Object&&global;var W="object"==typeof self&&self&&self.Object===Object&&self;const Z=q||W||Function("return this")();const G=Z.Symbol;var J=Object.prototype,X=J.hasOwnProperty,Q=J.toString,Y=G?G.toStringTag:void 0;const ee=function(e){var t=X.call(e,Y),n=e[Y];try{e[Y]=void 0;var r=!0}catch(e){}var o=Q.call(e);return r&&(t?e[Y]=n:delete e[Y]),o};var te=Object.prototype.toString;const ne=function(e){return te.call(e)};var re=G?G.toStringTag:void 0;const oe=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":re&&re in Object(e)?ee(e):ne(e)};const ie=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)};const se=function(e){if(!ie(e))return!1;var t=oe(e);return"[object Function]"==t||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t};const ae=Z["__core-js_shared__"];var ce,le=(ce=/[^.]+$/.exec(ae&&ae.keys&&ae.keys.IE_PROTO||""))?"Symbol(src)_1."+ce:"";const ue=function(e){return!!le&&le in e};var de=Function.prototype.toString;const ge=function(e){if(null!=e){try{return de.call(e)}catch(e){}try{return e+""}catch(e){}}return""};var he=/^\[object .+?Constructor\]$/,pe=Function.prototype,fe=Object.prototype,me=pe.toString,be=fe.hasOwnProperty,ve=RegExp("^"+me.call(be).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");const _e=function(e){return!(!ie(e)||ue(e))&&(se(e)?ve:he).test(ge(e))};const ke=function(e,t){return null==e?void 0:e[t]};const ye=function(e,t){var n=ke(e,t);return _e(n)?n:void 0};const we=ye(Z,"Map");const xe=ye(Object,"create");const Ie=function(){this.__data__=xe?xe(null):{},this.size=0};const je=function(e){var t=this.has(e)&&delete this.__data__[e];return this.size-=t?1:0,t};var Ae=Object.prototype.hasOwnProperty;const Ee=function(e){var t=this.__data__;if(xe){var n=t[e];return"__lodash_hash_undefined__"===n?void 0:n}return Ae.call(t,e)?t[e]:void 0};var Ce=Object.prototype.hasOwnProperty;const Se=function(e){var t=this.__data__;return xe?void 0!==t[e]:Ce.call(t,e)};const Oe=function(e,t){var n=this.__data__;return this.size+=this.has(e)?0:1,n[e]=xe&&void 0===t?"__lodash_hash_undefined__":t,this};function Pe(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}Pe.prototype.clear=Ie,Pe.prototype.delete=je,Pe.prototype.get=Ee,Pe.prototype.has=Se,Pe.prototype.set=Oe;const Le=Pe;const Ue=function(){this.size=0,this.__data__={hash:new Le,map:new(we||R),string:new Le}};const Te=function(e){var t=typeof e;return"string"==t||"number"==t||"symbol"==t||"boolean"==t?"__proto__"!==e:null===e};const Me=function(e,t){var n=e.__data__;return Te(t)?n["string"==typeof t?"string":"hash"]:n.map};const Be=function(e){var t=Me(this,e).delete(e);return this.size-=t?1:0,t};const ze=function(e){return Me(this,e).get(e)};const Fe=function(e){return Me(this,e).has(e)};const Ne=function(e,t){var n=Me(this,e),r=n.size;return n.set(e,t),this.size+=n.size==r?0:1,this};function Ke(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}Ke.prototype.clear=Ue,Ke.prototype.delete=Be,Ke.prototype.get=ze,Ke.prototype.has=Fe,Ke.prototype.set=Ne;const Re=Ke;const Ve=function(e,t){var n=this.__data__;if(n instanceof R){var r=n.__data__;if(!we||r.length<199)return r.push([e,t]),this.size=++n.size,this;n=this.__data__=new Re(r)}return n.set(e,t),this.size=n.size,this};function He(e){var t=this.__data__=new R(e);this.size=t.size}He.prototype.clear=V,He.prototype.delete=H,He.prototype.get=$,He.prototype.has=D,He.prototype.set=Ve;const $e=He;const De=function(e){return this.__data__.set(e,"__lodash_hash_undefined__"),this};const qe=function(e){return this.__data__.has(e)};function We(e){var t=-1,n=null==e?0:e.length;for(this.__data__=new Re;++t<n;)this.add(e[t])}We.prototype.add=We.prototype.push=De,We.prototype.has=qe;const Ze=We;const Ge=function(e,t){for(var n=-1,r=null==e?0:e.length;++n<r;)if(t(e[n],n,e))return!0;return!1};const Je=function(e,t){return e.has(t)};const Xe=function(e,t,n,r,o,i){var s=1&n,a=e.length,c=t.length;if(a!=c&&!(s&&c>a))return!1;var l=i.get(e),u=i.get(t);if(l&&u)return l==t&&u==e;var d=-1,g=!0,h=2&n?new Ze:void 0;for(i.set(e,t),i.set(t,e);++d<a;){var p=e[d],f=t[d];if(r)var m=s?r(f,p,d,t,e,i):r(p,f,d,e,t,i);if(void 0!==m){if(m)continue;g=!1;break}if(h){if(!Ge(t,(function(e,t){if(!Je(h,t)&&(p===e||o(p,e,n,r,i)))return h.push(t)}))){g=!1;break}}else if(p!==f&&!o(p,f,n,r,i)){g=!1;break}}return i.delete(e),i.delete(t),g};const Qe=Z.Uint8Array;const Ye=function(e){var t=-1,n=Array(e.size);return e.forEach((function(e,r){n[++t]=[r,e]})),n};const et=function(e){var t=-1,n=Array(e.size);return e.forEach((function(e){n[++t]=e})),n};var tt=G?G.prototype:void 0,nt=tt?tt.valueOf:void 0;const rt=function(e,t,n,r,o,i,s){switch(n){case"[object DataView]":if(e.byteLength!=t.byteLength||e.byteOffset!=t.byteOffset)return!1;e=e.buffer,t=t.buffer;case"[object ArrayBuffer]":return!(e.byteLength!=t.byteLength||!i(new Qe(e),new Qe(t)));case"[object Boolean]":case"[object Date]":case"[object Number]":return U(+e,+t);case"[object Error]":return e.name==t.name&&e.message==t.message;case"[object RegExp]":case"[object String]":return e==t+"";case"[object Map]":var a=Ye;case"[object Set]":var c=1&r;if(a||(a=et),e.size!=t.size&&!c)return!1;var l=s.get(e);if(l)return l==t;r|=2,s.set(e,t);var u=Xe(a(e),a(t),r,o,i,s);return s.delete(e),u;case"[object Symbol]":if(nt)return nt.call(e)==nt.call(t)}return!1};const ot=function(e,t){for(var n=-1,r=t.length,o=e.length;++n<r;)e[o+n]=t[n];return e};const it=Array.isArray;const st=function(e,t,n){var r=t(e);return it(e)?r:ot(r,n(e))};const at=function(e,t){for(var n=-1,r=null==e?0:e.length,o=0,i=[];++n<r;){var s=e[n];t(s,n,e)&&(i[o++]=s)}return i};const ct=function(){return[]};var lt=Object.prototype.propertyIsEnumerable,ut=Object.getOwnPropertySymbols;const dt=ut?function(e){return null==e?[]:(e=Object(e),at(ut(e),(function(t){return lt.call(e,t)})))}:ct;const gt=function(e,t){for(var n=-1,r=Array(e);++n<e;)r[n]=t(n);return r};const ht=function(e){return null!=e&&"object"==typeof e};const pt=function(e){return ht(e)&&"[object Arguments]"==oe(e)};var ft=Object.prototype,mt=ft.hasOwnProperty,bt=ft.propertyIsEnumerable;const vt=pt(function(){return arguments}())?pt:function(e){return ht(e)&&mt.call(e,"callee")&&!bt.call(e,"callee")};const _t=function(){return!1};var kt="object"==typeof exports&&exports&&!exports.nodeType&&exports,yt=kt&&"object"==typeof module&&module&&!module.nodeType&&module,wt=yt&&yt.exports===kt?Z.Buffer:void 0;const xt=(wt?wt.isBuffer:void 0)||_t;var It=/^(?:0|[1-9]\d*)$/;const jt=function(e,t){var n=typeof e;return!!(t=null==t?9007199254740991:t)&&("number"==n||"symbol"!=n&&It.test(e))&&e>-1&&e%1==0&&e<t};const At=function(e){return"number"==typeof e&&e>-1&&e%1==0&&e<=9007199254740991};var Et={};Et["[object Float32Array]"]=Et["[object Float64Array]"]=Et["[object Int8Array]"]=Et["[object Int16Array]"]=Et["[object Int32Array]"]=Et["[object Uint8Array]"]=Et["[object Uint8ClampedArray]"]=Et["[object Uint16Array]"]=Et["[object Uint32Array]"]=!0,Et["[object Arguments]"]=Et["[object Array]"]=Et["[object ArrayBuffer]"]=Et["[object Boolean]"]=Et["[object DataView]"]=Et["[object Date]"]=Et["[object Error]"]=Et["[object Function]"]=Et["[object Map]"]=Et["[object Number]"]=Et["[object Object]"]=Et["[object RegExp]"]=Et["[object Set]"]=Et["[object String]"]=Et["[object WeakMap]"]=!1;const Ct=function(e){return ht(e)&&At(e.length)&&!!Et[oe(e)]};const St=function(e){return function(t){return e(t)}};var Ot="object"==typeof exports&&exports&&!exports.nodeType&&exports,Pt=Ot&&"object"==typeof module&&module&&!module.nodeType&&module,Lt=Pt&&Pt.exports===Ot&&q.process,Ut=function(){try{var e=Pt&&Pt.require&&Pt.require("util").types;return e||Lt&&Lt.binding&&Lt.binding("util")}catch(e){}}();var Tt=Ut&&Ut.isTypedArray;const Mt=Tt?St(Tt):Ct;var Bt=Object.prototype.hasOwnProperty;const zt=function(e,t){var n=it(e),r=!n&&vt(e),o=!n&&!r&&xt(e),i=!n&&!r&&!o&&Mt(e),s=n||r||o||i,a=s?gt(e.length,String):[],c=a.length;for(var l in e)!t&&!Bt.call(e,l)||s&&("length"==l||o&&("offset"==l||"parent"==l)||i&&("buffer"==l||"byteLength"==l||"byteOffset"==l)||jt(l,c))||a.push(l);return a};var Ft=Object.prototype;const Nt=function(e){var t=e&&e.constructor;return e===("function"==typeof t&&t.prototype||Ft)};const Kt=function(e,t){return function(n){return e(t(n))}}(Object.keys,Object);var Rt=Object.prototype.hasOwnProperty;const Vt=function(e){if(!Nt(e))return Kt(e);var t=[];for(var n in Object(e))Rt.call(e,n)&&"constructor"!=n&&t.push(n);return t};const Ht=function(e){return null!=e&&At(e.length)&&!se(e)};const $t=function(e){return Ht(e)?zt(e):Vt(e)};const Dt=function(e){return st(e,$t,dt)};var qt=Object.prototype.hasOwnProperty;const Wt=function(e,t,n,r,o,i){var s=1&n,a=Dt(e),c=a.length;if(c!=Dt(t).length&&!s)return!1;for(var l=c;l--;){var u=a[l];if(!(s?u in t:qt.call(t,u)))return!1}var d=i.get(e),g=i.get(t);if(d&&g)return d==t&&g==e;var h=!0;i.set(e,t),i.set(t,e);for(var p=s;++l<c;){var f=e[u=a[l]],m=t[u];if(r)var b=s?r(m,f,u,t,e,i):r(f,m,u,e,t,i);if(!(void 0===b?f===m||o(f,m,n,r,i):b)){h=!1;break}p||(p="constructor"==u)}if(h&&!p){var v=e.constructor,_=t.constructor;v==_||!("constructor"in e)||!("constructor"in t)||"function"==typeof v&&v instanceof v&&"function"==typeof _&&_ instanceof _||(h=!1)}return i.delete(e),i.delete(t),h};const Zt=ye(Z,"DataView");const Gt=ye(Z,"Promise");const Jt=ye(Z,"Set");const Xt=ye(Z,"WeakMap");var Qt="[object Map]",Yt="[object Promise]",en="[object Set]",tn="[object WeakMap]",nn="[object DataView]",rn=ge(Zt),on=ge(we),sn=ge(Gt),an=ge(Jt),cn=ge(Xt),ln=oe;(Zt&&ln(new Zt(new ArrayBuffer(1)))!=nn||we&&ln(new we)!=Qt||Gt&&ln(Gt.resolve())!=Yt||Jt&&ln(new Jt)!=en||Xt&&ln(new Xt)!=tn)&&(ln=function(e){var t=oe(e),n="[object Object]"==t?e.constructor:void 0,r=n?ge(n):"";if(r)switch(r){case rn:return nn;case on:return Qt;case sn:return Yt;case an:return en;case cn:return tn}return t});const un=ln;var dn="[object Arguments]",gn="[object Array]",hn="[object Object]",pn=Object.prototype.hasOwnProperty;const fn=function(e,t,n,r,o,i){var s=it(e),a=it(t),c=s?gn:un(e),l=a?gn:un(t),u=(c=c==dn?hn:c)==hn,d=(l=l==dn?hn:l)==hn,g=c==l;if(g&&xt(e)){if(!xt(t))return!1;s=!0,u=!1}if(g&&!u)return i||(i=new $e),s||Mt(e)?Xe(e,t,n,r,o,i):rt(e,t,c,n,r,o,i);if(!(1&n)){var h=u&&pn.call(e,"__wrapped__"),p=d&&pn.call(t,"__wrapped__");if(h||p){var f=h?e.value():e,m=p?t.value():t;return i||(i=new $e),o(f,m,n,r,i)}}return!!g&&(i||(i=new $e),Wt(e,t,n,r,o,i))};const mn=function e(t,n,r,o,i){return t===n||(null==t||null==n||!ht(t)&&!ht(n)?t!=t&&n!=n:fn(t,n,r,o,e,i))};const bn=function(e,t){return mn(e,t)};class vn extends e.Command{constructor(e){super(e),this._wrapper=null,this._processInProgress=new Map,this.value=!1,this._prepareListeners()}refresh(){const e=this.editor;this.value=this._getValue();const t=e.model.document.selection.getSelectedElement(),n=t&&(t.is("element","imageInline")||t.is("element","imageBlock")),r=Array.from(this._processInProgress.values()).some((({element:e})=>bn(e,t)));n&&t.hasAttribute("ckboxImageId")&&!r?this.isEnabled=!0:this.isEnabled=!1}execute(){if(this._getValue())return;this.value=!0,this._wrapper=(0,s.createElement)(document,"div",{class:"ck ckbox-wrapper"}),document.body.appendChild(this._wrapper);const e=this.editor.model.document.selection.getSelectedElement(),t={ckboxImageId:e.getAttribute("ckboxImageId"),element:e,controller:new AbortController};window.CKBox.mountImageEditor(this._wrapper,this._prepareOptions(t))}destroy(){this._handleImageEditorClose();for(const e of this._processInProgress.values())e.controller.abort();super.destroy()}_getValue(){return null!==this._wrapper}_prepareOptions(e){const t=this.editor.config.get("ckbox");return{assetId:e.ckboxImageId,imageEditing:{allowOverwrite:!1},tokenUrl:t.tokenUrl,onClose:()=>this._handleImageEditorClose(),onSave:t=>this._handleImageEditorSave(e,t)}}_prepareListeners(){this.listenTo(this.editor.model.document,"change:data",(()=>{this._getProcessingStatesOfDeletedImages().forEach((e=>{e.controller.abort()}))}))}_getProcessingStatesOfDeletedImages(){const e=[];for(const t of this._processInProgress.values())"$graveyard"==t.element.root.rootName&&e.push(t);return e}_handleImageEditorClose(){this._wrapper&&(this._wrapper.remove(),this._wrapper=null,this.editor.editing.view.focus())}_handleImageEditorSave(n,r){const o=this.editor.locale.t,i=this.editor.plugins.get(t.Notification),a=this.editor.plugins.get(e.PendingActions),c=a.add(o("Processing the edited image."));this._processInProgress.set(n.ckboxImageId,n),this._showImageProcessingIndicator(n.element,r),this.refresh(),this._waitForAssetProcessed(r.data.id,n.controller.signal).then((e=>{this._replaceImage(n.element,e)}),(e=>{this.editor.editing.reconvertItem(n.element),n.controller.signal.aborted||(!e||e instanceof s.CKEditorError?i.showWarning(o("Server failed to process the image."),{namespace:"ckbox"}):console.error(e))})).finally((()=>{this._processInProgress.delete(n.ckboxImageId),a.remove(c),this.refresh()}))}async _getAssetStatusFromServer(e,t){const n=this.editor.plugins.get(E),r=new URL("assets/"+e,this.editor.config.get("ckbox.serviceOrigin")),o=await _({url:r,signal:t,authorization:n.getToken().value}),i=o.metadata.metadataProcessingStatus;if(!i||"queued"==i)throw new s.CKEditorError("ckbox-image-not-processed");return{data:{...o}}}async _waitForAssetProcessed(e,t){const n=await(0,s.retry)((()=>this._getAssetStatusFromServer(e,t)),{signal:t,maxAttempts:5});if("success"!=n.data.metadata.metadataProcessingStatus)throw new s.CKEditorError("ckbox-image-processing-failed");return n}_showImageProcessingIndicator(e,t){const n=this.editor;n.editing.view.change((r=>{const o=n.editing.mapper.toViewElement(e),i=this.editor.plugins.get("ImageUtils").findViewImgElement(o);r.removeStyle("aspect-ratio",i),r.setAttribute("width",t.data.metadata.width,i),r.setAttribute("height",t.data.metadata.height,i),r.setStyle("width",`${t.data.metadata.width}px`,i),r.setStyle("height",`${t.data.metadata.height}px`,i),r.addClass("image-processing",o)}))}_replaceImage(e,t){const n=this.editor,{imageFallbackUrl:r,imageSources:o,imageWidth:i,imageHeight:s,imagePlaceholder:a}=y(t),c=Array.from(n.model.document.selection.getRanges());n.model.change((l=>{l.setSelection(e,"on"),n.execute("insertImage",{source:{src:r,sources:o,alt:e.getAttribute("alt"),width:i,height:s,...a?{placeholder:a}:null}});const u=e.getChildren();e=n.model.document.selection.getSelectedElement();for(const t of u)l.append(l.cloneElement(t),e);l.setAttribute("ckboxImageId",t.data.id,e),l.setSelection(c)}))}}class _n extends e.Plugin{static get pluginName(){return"CKBoxImageEditEditing"}static get requires(){return[e.PendingActions,t.Notification,"ImageUtils","ImageEditing"]}init(){const{editor:e}=this;e.commands.add("ckboxImageEdit",new vn(e))}}class kn extends e.Plugin{static get pluginName(){return"CKBoxImageEditUI"}init(){const e=this.editor;e.ui.componentFactory.add("ckboxImageEdit",(n=>{const r=e.commands.get("ckboxImageEdit"),o=new t.ButtonView(n),i=n.t;return o.set({label:i("Edit image"),icon:'<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="M5.802 8.942a.607.607 0 0 0-.838-.029L1.429 12.8V3.158h12.93v5.25l1.429-1.319V2.758c0-.553-.467-1-1.039-1H1.05c-.582 0-1.049.447-1.049 1v11.281c0 .562.467 1.01 1.039 1.01h6.583v-.228c0-.124.052-.242.143-.326l4.504-4.157-.312-.367a.61.61 0 0 0-.829 0l-2.124 1.962-3.202-2.991Zm3.74-2.578a1.87 1.87 0 1 0 3.707-.486 1.87 1.87 0 0 0-3.707.486Z"/><path d="M8.874 15.926v2.316h2.317l6.836-6.834-2.32-2.32-6.833 6.84v-.002Zm10.944-6.312a.612.612 0 0 0 0-.87L18.372 7.3a.614.614 0 0 0-.87 0l-1.133 1.128 2.32 2.319 1.13-1.133Z"/></svg>',tooltip:!0}),o.bind("isOn").to(r,"value",r,"isEnabled",((e,t)=>e&&t)),o.bind("isEnabled").to(r),this.listenTo(o,"execute",(()=>{e.execute("ckboxImageEdit"),e.editing.view.focus()})),o}))}}var yn=n(62),wn=n.n(yn),xn=n(70),In={injectType:"singletonStyleTag",attributes:{"data-cke":!0},insert:"head",singleton:!0};wn()(xn.Z,In);xn.Z.locals;class jn extends e.Plugin{static get pluginName(){return"CKBoxImageEdit"}static get requires(){return[E,_n,kn]}}})(),(window.CKEditor5=window.CKEditor5||{}).ckbox=r})();
@@ -33,6 +33,23 @@
33
33
  "_comment": "If `config.ckbox.ignoreDataId` is set to false (off), the asset ID as the `data-ckbox-resource-id` attribute is added on the inserted elements (by default)."
34
34
  }
35
35
  ]
36
+ },
37
+ {
38
+ "name": "CKBox Image Edit",
39
+ "className": "CKBoxImageEdit",
40
+ "description": "Allows editing images.",
41
+ "docs": "features/file-management/ckbox.html",
42
+ "path": "src/ckboximageedit.js",
43
+ "requires": [
44
+ "CKBox"
45
+ ],
46
+ "uiComponents": [
47
+ {
48
+ "name": "ckboxImageEdit",
49
+ "type": "Button",
50
+ "iconPath": "theme/icons/ckbox-image-edit.svg"
51
+ }
52
+ ]
36
53
  }
37
54
  ]
38
55
  }
@@ -1,5 +1,8 @@
1
1
  {
2
- "Open file manager": "Toolbar button tooltip for opening a file browser that allows inserting an image or a file to the editor.",
2
+ "Open file manager": "A toolbar button tooltip for opening the file browser that allows inserting an image or a file to the editor.",
3
3
  "Cannot determine a category for the uploaded file.": "A message is displayed when CKEditor 5 cannot associate an image with any of the categories defined in CKBox while uploading an asset.",
4
- "Cannot access default workspace.": "A message is displayed when the user is not authorised to access CKBox workspace configured as default one."
4
+ "Cannot access default workspace.": "A message is displayed when the user is not authorised to access the CKBox workspace configured as default one.",
5
+ "Edit image": "Image toolbar button tooltip for opening a dialog to manipulate the image.",
6
+ "Processing the edited image.": "A message stating that image editing is in progress.",
7
+ "Server failed to process the image.": "A message is displayed when the server fails to process an image or doesn't respond."
5
8
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-ckbox",
3
- "version": "0.0.0-nightly-20231121.0",
3
+ "version": "0.0.0-nightly-20231123.0",
4
4
  "description": "CKBox integration for CKEditor 5.",
5
5
  "keywords": [
6
6
  "ckeditor",
@@ -12,8 +12,9 @@
12
12
  ],
13
13
  "main": "src/index.js",
14
14
  "dependencies": {
15
- "ckeditor5": "0.0.0-nightly-20231121.0",
16
- "blurhash": "^2.0.5"
15
+ "ckeditor5": "0.0.0-nightly-20231123.0",
16
+ "blurhash": "^2.0.5",
17
+ "lodash-es": "4.17.21"
17
18
  },
18
19
  "author": "CKSource (http://cksource.com/)",
19
20
  "license": "GPL-2.0-or-later",
@@ -2,7 +2,7 @@
2
2
  * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
- import type { CKBox, CKBoxCommand, CKBoxConfig, CKBoxEditing } from './index';
5
+ import type { CKBox, CKBoxCommand, CKBoxConfig, CKBoxEditing, CKBoxImageEdit, CKBoxImageEditEditing, CKBoxImageEditCommand, CKBoxImageEditUI } from './index';
6
6
  declare module '@ckeditor/ckeditor5-core' {
7
7
  interface EditorConfig {
8
8
  /**
@@ -15,8 +15,18 @@ declare module '@ckeditor/ckeditor5-core' {
15
15
  interface PluginsMap {
16
16
  [CKBox.pluginName]: CKBox;
17
17
  [CKBoxEditing.pluginName]: CKBoxEditing;
18
+ [CKBoxImageEdit.pluginName]: CKBoxImageEdit;
19
+ [CKBoxImageEditEditing.pluginName]: CKBoxImageEditEditing;
20
+ [CKBoxImageEditUI.pluginName]: CKBoxImageEditUI;
18
21
  }
19
22
  interface CommandsMap {
20
23
  ckbox: CKBoxCommand;
24
+ ckboxImageEdit: CKBoxImageEditCommand;
21
25
  }
22
26
  }
27
+ declare global {
28
+ var CKBox: {
29
+ mount(wrapper: Element, options: Record<string, unknown>): void;
30
+ mountImageEditor(wrapper: Element, options: Record<string, unknown>): void;
31
+ };
32
+ }
@@ -3,12 +3,7 @@
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  import { Command, type Editor } from 'ckeditor5/src/core';
6
- import type { CKBoxAssetDefinition } from './ckboxconfig';
7
- declare global {
8
- var CKBox: {
9
- mount(wrapper: Element, options: Record<string, unknown>): void;
10
- };
11
- }
6
+ import type { CKBoxAssetDefinition, CKBoxAssetImageAttributesDefinition, CKBoxRawAssetDefinition } from './ckboxconfig';
12
7
  /**
13
8
  * The CKBox command. It is used by the {@link module:ckbox/ckboxediting~CKBoxEditing CKBox editing feature} to open the CKBox file manager.
14
9
  * The file manager allows inserting an image or a link to a file into the editor content.
@@ -110,3 +105,9 @@ export default class CKBoxCommand extends Command {
110
105
  */
111
106
  private _insertLink;
112
107
  }
108
+ /**
109
+ * Parses the assets attributes into the internal data format.
110
+ *
111
+ * @internal
112
+ */
113
+ export declare function prepareImageAssetAttributes(asset: CKBoxRawAssetDefinition): CKBoxAssetImageAttributesDefinition;
@@ -281,8 +281,10 @@ function prepareAssets({ assets, isImageAllowed, isLinkAllowed }) {
281
281
  }
282
282
  /**
283
283
  * Parses the assets attributes into the internal data format.
284
+ *
285
+ * @internal
284
286
  */
285
- function prepareImageAssetAttributes(asset) {
287
+ export function prepareImageAssetAttributes(asset) {
286
288
  const { imageFallbackUrl, imageSources } = getImageUrls(asset.data.imageUrls);
287
289
  const { description, width, height, blurHash } = asset.data.metadata;
288
290
  const imagePlaceholder = blurHashToDataUrl(blurHash);
@@ -85,6 +85,10 @@ export interface CKBoxConfig {
85
85
  * If defined, it is an error, when the user has no access to the specified workspace.
86
86
  */
87
87
  defaultUploadWorkspaceId?: string;
88
+ /**
89
+ * Enforces displaying the "Powered by CKBox" link regardless of the CKBox plan used.
90
+ */
91
+ forceDemoLabel?: boolean;
88
92
  /**
89
93
  * Inserts the unique asset ID as the `data-ckbox-resource-id` attribute. To disable this behavior, set it to `true`.
90
94
  *
@@ -296,4 +300,8 @@ export interface CKBoxRawAssetMetadataDefinition {
296
300
  * The blurhash placeholder value.
297
301
  */
298
302
  blurHash?: string;
303
+ /**
304
+ * The processing status of the asset.
305
+ */
306
+ metadataProcessingStatus?: string;
299
307
  }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module ckbox/ckboximageedit/ckboximageeditcommand
7
+ */
8
+ import { Command, type Editor } from 'ckeditor5/src/core';
9
+ /**
10
+ * The CKBox edit image command.
11
+ *
12
+ * Opens the CKBox dialog for editing the image.
13
+ */
14
+ export default class CKBoxImageEditCommand extends Command {
15
+ /**
16
+ * Flag indicating whether the command is active, i.e. dialog is open.
17
+ */
18
+ value: boolean;
19
+ /**
20
+ * The DOM element that acts as a mounting point for the CKBox Edit Image dialog.
21
+ */
22
+ private _wrapper;
23
+ /**
24
+ * The states of image processing in progress.
25
+ */
26
+ private _processInProgress;
27
+ /**
28
+ * @inheritDoc
29
+ */
30
+ constructor(editor: Editor);
31
+ /**
32
+ * @inheritDoc
33
+ */
34
+ refresh(): void;
35
+ /**
36
+ * Opens the CKBox Image Editor dialog for editing the image.
37
+ */
38
+ execute(): void;
39
+ /**
40
+ * @inheritDoc
41
+ */
42
+ destroy(): void;
43
+ /**
44
+ * Indicates if the CKBox Image Editor dialog is already opened.
45
+ */
46
+ private _getValue;
47
+ /**
48
+ * Creates the options object for the CKBox Image Editor dialog.
49
+ */
50
+ private _prepareOptions;
51
+ /**
52
+ * Initializes event lister for an event of removing an image.
53
+ */
54
+ private _prepareListeners;
55
+ /**
56
+ * Gets processing states of images that have been deleted in the mean time.
57
+ */
58
+ private _getProcessingStatesOfDeletedImages;
59
+ /**
60
+ * Closes the CKBox Image Editor dialog.
61
+ */
62
+ private _handleImageEditorClose;
63
+ /**
64
+ * Save edited image. In case server respond with "success" replace with edited image,
65
+ * otherwise show notification error.
66
+ */
67
+ private _handleImageEditorSave;
68
+ /**
69
+ * Get asset's status on server. If server responds with "success" status then
70
+ * image is already proceeded and ready for saving.
71
+ */
72
+ private _getAssetStatusFromServer;
73
+ /**
74
+ * Waits for an asset to be processed.
75
+ * It retries retrieving asset status from the server in case of failure.
76
+ */
77
+ private _waitForAssetProcessed;
78
+ /**
79
+ * Shows processing indicator while image is processing.
80
+ *
81
+ * @param asset Data about certain asset.
82
+ */
83
+ private _showImageProcessingIndicator;
84
+ /**
85
+ * Replace the edited image with the new one.
86
+ */
87
+ private _replaceImage;
88
+ }
@@ -0,0 +1,266 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /* globals document, console, AbortController, URL, window */
6
+ /**
7
+ * @module ckbox/ckboximageedit/ckboximageeditcommand
8
+ */
9
+ import { Command, PendingActions } from 'ckeditor5/src/core';
10
+ import { CKEditorError, createElement, retry } from 'ckeditor5/src/utils';
11
+ import { Notification } from 'ckeditor5/src/ui';
12
+ import { isEqual } from 'lodash-es';
13
+ import CKBoxEditing from '../ckboxediting';
14
+ import { sendHttpRequest } from '../utils';
15
+ import { prepareImageAssetAttributes } from '../ckboxcommand';
16
+ /**
17
+ * The CKBox edit image command.
18
+ *
19
+ * Opens the CKBox dialog for editing the image.
20
+ */
21
+ export default class CKBoxImageEditCommand extends Command {
22
+ /**
23
+ * @inheritDoc
24
+ */
25
+ constructor(editor) {
26
+ super(editor);
27
+ /**
28
+ * The DOM element that acts as a mounting point for the CKBox Edit Image dialog.
29
+ */
30
+ this._wrapper = null;
31
+ /**
32
+ * The states of image processing in progress.
33
+ */
34
+ this._processInProgress = new Map();
35
+ this.value = false;
36
+ this._prepareListeners();
37
+ }
38
+ /**
39
+ * @inheritDoc
40
+ */
41
+ refresh() {
42
+ const editor = this.editor;
43
+ this.value = this._getValue();
44
+ const selectedElement = editor.model.document.selection.getSelectedElement();
45
+ const isImageElement = selectedElement && (selectedElement.is('element', 'imageInline') ||
46
+ selectedElement.is('element', 'imageBlock'));
47
+ const isBeingProcessed = Array.from(this._processInProgress.values())
48
+ .some(({ element }) => isEqual(element, selectedElement));
49
+ if (isImageElement && selectedElement.hasAttribute('ckboxImageId') && !isBeingProcessed) {
50
+ this.isEnabled = true;
51
+ }
52
+ else {
53
+ this.isEnabled = false;
54
+ }
55
+ }
56
+ /**
57
+ * Opens the CKBox Image Editor dialog for editing the image.
58
+ */
59
+ execute() {
60
+ if (this._getValue()) {
61
+ return;
62
+ }
63
+ this.value = true;
64
+ this._wrapper = createElement(document, 'div', { class: 'ck ckbox-wrapper' });
65
+ document.body.appendChild(this._wrapper);
66
+ const imageElement = this.editor.model.document.selection.getSelectedElement();
67
+ const ckboxImageId = imageElement.getAttribute('ckboxImageId');
68
+ const processingState = {
69
+ ckboxImageId,
70
+ element: imageElement,
71
+ controller: new AbortController()
72
+ };
73
+ window.CKBox.mountImageEditor(this._wrapper, this._prepareOptions(processingState));
74
+ }
75
+ /**
76
+ * @inheritDoc
77
+ */
78
+ destroy() {
79
+ this._handleImageEditorClose();
80
+ for (const state of this._processInProgress.values()) {
81
+ state.controller.abort();
82
+ }
83
+ super.destroy();
84
+ }
85
+ /**
86
+ * Indicates if the CKBox Image Editor dialog is already opened.
87
+ */
88
+ _getValue() {
89
+ return this._wrapper !== null;
90
+ }
91
+ /**
92
+ * Creates the options object for the CKBox Image Editor dialog.
93
+ */
94
+ _prepareOptions(state) {
95
+ const editor = this.editor;
96
+ const ckboxConfig = editor.config.get('ckbox');
97
+ return {
98
+ assetId: state.ckboxImageId,
99
+ imageEditing: {
100
+ allowOverwrite: false
101
+ },
102
+ tokenUrl: ckboxConfig.tokenUrl,
103
+ onClose: () => this._handleImageEditorClose(),
104
+ onSave: (asset) => this._handleImageEditorSave(state, asset)
105
+ };
106
+ }
107
+ /**
108
+ * Initializes event lister for an event of removing an image.
109
+ */
110
+ _prepareListeners() {
111
+ // Abort editing processing when the image has been removed.
112
+ this.listenTo(this.editor.model.document, 'change:data', () => {
113
+ const processingStates = this._getProcessingStatesOfDeletedImages();
114
+ processingStates.forEach(processingState => {
115
+ processingState.controller.abort();
116
+ });
117
+ });
118
+ }
119
+ /**
120
+ * Gets processing states of images that have been deleted in the mean time.
121
+ */
122
+ _getProcessingStatesOfDeletedImages() {
123
+ const states = [];
124
+ for (const state of this._processInProgress.values()) {
125
+ if (state.element.root.rootName == '$graveyard') {
126
+ states.push(state);
127
+ }
128
+ }
129
+ return states;
130
+ }
131
+ /**
132
+ * Closes the CKBox Image Editor dialog.
133
+ */
134
+ _handleImageEditorClose() {
135
+ if (!this._wrapper) {
136
+ return;
137
+ }
138
+ this._wrapper.remove();
139
+ this._wrapper = null;
140
+ this.editor.editing.view.focus();
141
+ }
142
+ /**
143
+ * Save edited image. In case server respond with "success" replace with edited image,
144
+ * otherwise show notification error.
145
+ */
146
+ _handleImageEditorSave(state, asset) {
147
+ const t = this.editor.locale.t;
148
+ const notification = this.editor.plugins.get(Notification);
149
+ const pendingActions = this.editor.plugins.get(PendingActions);
150
+ const action = pendingActions.add(t('Processing the edited image.'));
151
+ this._processInProgress.set(state.ckboxImageId, state);
152
+ this._showImageProcessingIndicator(state.element, asset);
153
+ this.refresh();
154
+ this._waitForAssetProcessed(asset.data.id, state.controller.signal)
155
+ .then(asset => {
156
+ this._replaceImage(state.element, asset);
157
+ }, error => {
158
+ // Remove processing indicator. It was added only to ViewElement.
159
+ this.editor.editing.reconvertItem(state.element);
160
+ if (state.controller.signal.aborted) {
161
+ return;
162
+ }
163
+ if (!error || error instanceof CKEditorError) {
164
+ notification.showWarning(t('Server failed to process the image.'), {
165
+ namespace: 'ckbox'
166
+ });
167
+ }
168
+ else {
169
+ console.error(error);
170
+ }
171
+ }).finally(() => {
172
+ this._processInProgress.delete(state.ckboxImageId);
173
+ pendingActions.remove(action);
174
+ this.refresh();
175
+ });
176
+ }
177
+ /**
178
+ * Get asset's status on server. If server responds with "success" status then
179
+ * image is already proceeded and ready for saving.
180
+ */
181
+ async _getAssetStatusFromServer(id, signal) {
182
+ const ckboxEditing = this.editor.plugins.get(CKBoxEditing);
183
+ const url = new URL('assets/' + id, this.editor.config.get('ckbox.serviceOrigin'));
184
+ const response = await sendHttpRequest({
185
+ url,
186
+ signal,
187
+ authorization: ckboxEditing.getToken().value
188
+ });
189
+ const status = response.metadata.metadataProcessingStatus;
190
+ if (!status || status == 'queued') {
191
+ /**
192
+ * Image has not been processed yet.
193
+ *
194
+ * @error ckbox-image-not-processed
195
+ */
196
+ throw new CKEditorError('ckbox-image-not-processed');
197
+ }
198
+ return { data: { ...response } };
199
+ }
200
+ /**
201
+ * Waits for an asset to be processed.
202
+ * It retries retrieving asset status from the server in case of failure.
203
+ */
204
+ async _waitForAssetProcessed(id, signal) {
205
+ const result = await retry(() => this._getAssetStatusFromServer(id, signal), {
206
+ signal,
207
+ maxAttempts: 5
208
+ });
209
+ if (result.data.metadata.metadataProcessingStatus != 'success') {
210
+ /**
211
+ * The image processing failed.
212
+ *
213
+ * @error ckbox-image-processing-failed
214
+ */
215
+ throw new CKEditorError('ckbox-image-processing-failed');
216
+ }
217
+ return result;
218
+ }
219
+ /**
220
+ * Shows processing indicator while image is processing.
221
+ *
222
+ * @param asset Data about certain asset.
223
+ */
224
+ _showImageProcessingIndicator(element, asset) {
225
+ const editor = this.editor;
226
+ editor.editing.view.change(writer => {
227
+ const imageElementView = editor.editing.mapper.toViewElement(element);
228
+ const imageUtils = this.editor.plugins.get('ImageUtils');
229
+ const img = imageUtils.findViewImgElement(imageElementView);
230
+ writer.removeStyle('aspect-ratio', img);
231
+ writer.setAttribute('width', asset.data.metadata.width, img);
232
+ writer.setAttribute('height', asset.data.metadata.height, img);
233
+ writer.setStyle('width', `${asset.data.metadata.width}px`, img);
234
+ writer.setStyle('height', `${asset.data.metadata.height}px`, img);
235
+ writer.addClass('image-processing', imageElementView);
236
+ });
237
+ }
238
+ /**
239
+ * Replace the edited image with the new one.
240
+ */
241
+ _replaceImage(element, asset) {
242
+ const editor = this.editor;
243
+ const { imageFallbackUrl, imageSources, imageWidth, imageHeight, imagePlaceholder } = prepareImageAssetAttributes(asset);
244
+ const previousSelectionRanges = Array.from(editor.model.document.selection.getRanges());
245
+ editor.model.change(writer => {
246
+ writer.setSelection(element, 'on');
247
+ editor.execute('insertImage', {
248
+ source: {
249
+ src: imageFallbackUrl,
250
+ sources: imageSources,
251
+ alt: element.getAttribute('alt'),
252
+ width: imageWidth,
253
+ height: imageHeight,
254
+ ...(imagePlaceholder ? { placeholder: imagePlaceholder } : null)
255
+ }
256
+ });
257
+ const previousChildren = element.getChildren();
258
+ element = editor.model.document.selection.getSelectedElement();
259
+ for (const child of previousChildren) {
260
+ writer.append(writer.cloneElement(child), element);
261
+ }
262
+ writer.setAttribute('ckboxImageId', asset.data.id, element);
263
+ writer.setSelection(previousSelectionRanges);
264
+ });
265
+ }
266
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module ckbox/ckboximageedit/ckboximageeditediting
7
+ */
8
+ import { PendingActions, Plugin } from 'ckeditor5/src/core';
9
+ import { Notification } from 'ckeditor5/src/ui';
10
+ /**
11
+ * The CKBox image edit editing plugin.
12
+ */
13
+ export default class CKBoxImageEditEditing extends Plugin {
14
+ /**
15
+ * @inheritDoc
16
+ */
17
+ static get pluginName(): "CKBoxImageEditEditing";
18
+ /**
19
+ * @inheritDoc
20
+ */
21
+ static get requires(): readonly [typeof PendingActions, typeof Notification, "ImageUtils", "ImageEditing"];
22
+ /**
23
+ * @inheritDoc
24
+ */
25
+ init(): void;
26
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module ckbox/ckboximageedit/ckboximageeditediting
7
+ */
8
+ import { PendingActions, Plugin } from 'ckeditor5/src/core';
9
+ import { Notification } from 'ckeditor5/src/ui';
10
+ import CKBoxImageEditCommand from './ckboximageeditcommand';
11
+ /**
12
+ * The CKBox image edit editing plugin.
13
+ */
14
+ export default class CKBoxImageEditEditing extends Plugin {
15
+ /**
16
+ * @inheritDoc
17
+ */
18
+ static get pluginName() {
19
+ return 'CKBoxImageEditEditing';
20
+ }
21
+ /**
22
+ * @inheritDoc
23
+ */
24
+ static get requires() {
25
+ return [PendingActions, Notification, 'ImageUtils', 'ImageEditing'];
26
+ }
27
+ /**
28
+ * @inheritDoc
29
+ */
30
+ init() {
31
+ const { editor } = this;
32
+ editor.commands.add('ckboxImageEdit', new CKBoxImageEditCommand(editor));
33
+ }
34
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module ckbox/ckboximageedit/ckboximageeditui
7
+ */
8
+ import { Plugin } from 'ckeditor5/src/core';
9
+ /**
10
+ * The UI plugin of the CKBox image edit feature.
11
+ *
12
+ * It registers the `'ckboxImageEdit'` UI button in the editor's {@link module:ui/componentfactory~ComponentFactory component factory}
13
+ * that allows you to open the CKBox dialog and edit the image.
14
+ */
15
+ export default class CKBoxImageEditUI extends Plugin {
16
+ /**
17
+ * @inheritDoc
18
+ */
19
+ static get pluginName(): "CKBoxImageEditUI";
20
+ /**
21
+ * @inheritDoc
22
+ */
23
+ init(): void;
24
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module ckbox/ckboximageedit/ckboximageeditui
7
+ */
8
+ import { Plugin } from 'ckeditor5/src/core';
9
+ import { ButtonView } from 'ckeditor5/src/ui';
10
+ import ckboxImageEditIcon from '../../theme/icons/ckbox-image-edit.svg';
11
+ /**
12
+ * The UI plugin of the CKBox image edit feature.
13
+ *
14
+ * It registers the `'ckboxImageEdit'` UI button in the editor's {@link module:ui/componentfactory~ComponentFactory component factory}
15
+ * that allows you to open the CKBox dialog and edit the image.
16
+ */
17
+ export default class CKBoxImageEditUI extends Plugin {
18
+ /**
19
+ * @inheritDoc
20
+ */
21
+ static get pluginName() {
22
+ return 'CKBoxImageEditUI';
23
+ }
24
+ /**
25
+ * @inheritDoc
26
+ */
27
+ init() {
28
+ const editor = this.editor;
29
+ editor.ui.componentFactory.add('ckboxImageEdit', locale => {
30
+ const command = editor.commands.get('ckboxImageEdit');
31
+ const view = new ButtonView(locale);
32
+ const t = locale.t;
33
+ view.set({
34
+ label: t('Edit image'),
35
+ icon: ckboxImageEditIcon,
36
+ tooltip: true
37
+ });
38
+ view.bind('isOn').to(command, 'value', command, 'isEnabled', (value, isEnabled) => value && isEnabled);
39
+ view.bind('isEnabled').to(command);
40
+ // Execute the command.
41
+ this.listenTo(view, 'execute', () => {
42
+ editor.execute('ckboxImageEdit');
43
+ editor.editing.view.focus();
44
+ });
45
+ return view;
46
+ });
47
+ }
48
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module ckbox/ckboximageedit
7
+ */
8
+ import { Plugin } from 'ckeditor5/src/core';
9
+ import CKBoxEditing from './ckboxediting';
10
+ import CKBoxImageEditEditing from './ckboximageedit/ckboximageeditediting';
11
+ import CKBoxImageEditUI from './ckboximageedit/ckboximageeditui';
12
+ import '../theme/ckboximageedit.css';
13
+ /**
14
+ * The CKBox image edit feature.
15
+ */
16
+ export default class CKBoxImageEdit extends Plugin {
17
+ /**
18
+ * @inheritDoc
19
+ */
20
+ static get pluginName(): "CKBoxImageEdit";
21
+ /**
22
+ * @inheritDoc
23
+ */
24
+ static get requires(): readonly [typeof CKBoxEditing, typeof CKBoxImageEditEditing, typeof CKBoxImageEditUI];
25
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module ckbox/ckboximageedit
7
+ */
8
+ import { Plugin } from 'ckeditor5/src/core';
9
+ import CKBoxEditing from './ckboxediting';
10
+ import CKBoxImageEditEditing from './ckboximageedit/ckboximageeditediting';
11
+ import CKBoxImageEditUI from './ckboximageedit/ckboximageeditui';
12
+ import '../theme/ckboximageedit.css';
13
+ /**
14
+ * The CKBox image edit feature.
15
+ */
16
+ export default class CKBoxImageEdit extends Plugin {
17
+ /**
18
+ * @inheritDoc
19
+ */
20
+ static get pluginName() {
21
+ return 'CKBoxImageEdit';
22
+ }
23
+ /**
24
+ * @inheritDoc
25
+ */
26
+ static get requires() {
27
+ return [CKBoxEditing, CKBoxImageEditEditing, CKBoxImageEditUI];
28
+ }
29
+ }
@@ -2,7 +2,7 @@
2
2
  * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
- /* globals AbortController, FormData, URL, XMLHttpRequest, window */
5
+ /* globals AbortController, FormData, URL, window */
6
6
  /**
7
7
  * @module ckbox/ckboxuploadadapter
8
8
  */
@@ -10,7 +10,7 @@ import { Plugin } from 'ckeditor5/src/core';
10
10
  import { FileRepository } from 'ckeditor5/src/upload';
11
11
  import { logError } from 'ckeditor5/src/utils';
12
12
  import CKBoxEditing from './ckboxediting';
13
- import { getImageUrls, getWorkspaceId } from './utils';
13
+ import { getImageUrls, getWorkspaceId, sendHttpRequest } from './utils';
14
14
  /**
15
15
  * A plugin that enables file uploads in CKEditor 5 using the CKBox server–side connector.
16
16
  * See the {@glink features/file-management/ckbox CKBox file manager integration} guide to learn how to configure
@@ -107,7 +107,11 @@ class Adapter {
107
107
  categoryUrl.searchParams.set('limit', ITEMS_PER_REQUEST.toString());
108
108
  categoryUrl.searchParams.set('offset', offset.toString());
109
109
  categoryUrl.searchParams.set('workspaceId', this.getWorkspaceId());
110
- return this._sendHttpRequest({ url: categoryUrl })
110
+ return sendHttpRequest({
111
+ url: categoryUrl,
112
+ signal: this.controller.signal,
113
+ authorization: this.token.value
114
+ })
111
115
  .then(async (data) => {
112
116
  const remainingItems = data.totalCount - (offset + ITEMS_PER_REQUEST);
113
117
  if (remainingItems > 0) {
@@ -190,9 +194,11 @@ class Adapter {
190
194
  this.loader.uploadTotal = evt.total;
191
195
  this.loader.uploaded = evt.loaded;
192
196
  }
193
- }
197
+ },
198
+ signal: this.controller.signal,
199
+ authorization: this.token.value
194
200
  };
195
- return this._sendHttpRequest(requestConfig)
201
+ return sendHttpRequest(requestConfig)
196
202
  .then(async (data) => {
197
203
  const imageUrls = getImageUrls(data.imageUrls);
198
204
  return {
@@ -214,56 +220,6 @@ class Adapter {
214
220
  abort() {
215
221
  this.controller.abort();
216
222
  }
217
- /**
218
- * Sends the HTTP request.
219
- *
220
- * @param config.url the URL where the request will be sent.
221
- * @param config.method The HTTP method.
222
- * @param config.data Additional data to send.
223
- * @param config.onUploadProgress A callback informing about the upload progress.
224
- */
225
- _sendHttpRequest({ url, method = 'GET', data, onUploadProgress }) {
226
- const signal = this.controller.signal;
227
- const xhr = new XMLHttpRequest();
228
- xhr.open(method, url.toString(), true);
229
- xhr.setRequestHeader('Authorization', this.token.value);
230
- xhr.setRequestHeader('CKBox-Version', 'CKEditor 5');
231
- xhr.responseType = 'json';
232
- // The callback is attached to the `signal#abort` event.
233
- const abortCallback = () => {
234
- xhr.abort();
235
- };
236
- return new Promise((resolve, reject) => {
237
- signal.addEventListener('abort', abortCallback);
238
- xhr.addEventListener('loadstart', () => {
239
- signal.addEventListener('abort', abortCallback);
240
- });
241
- xhr.addEventListener('loadend', () => {
242
- signal.removeEventListener('abort', abortCallback);
243
- });
244
- xhr.addEventListener('error', () => {
245
- reject();
246
- });
247
- xhr.addEventListener('abort', () => {
248
- reject();
249
- });
250
- xhr.addEventListener('load', async () => {
251
- const response = xhr.response;
252
- if (!response || response.statusCode >= 400) {
253
- return reject(response && response.message);
254
- }
255
- return resolve(response);
256
- });
257
- /* istanbul ignore else -- @preserve */
258
- if (onUploadProgress) {
259
- xhr.upload.addEventListener('progress', evt => {
260
- onUploadProgress(evt);
261
- });
262
- }
263
- // Send the request.
264
- xhr.send(data);
265
- });
266
- }
267
223
  }
268
224
  /**
269
225
  * Returns an extension from the given value.
package/src/index.d.ts CHANGED
@@ -8,6 +8,10 @@
8
8
  export { default as CKBox } from './ckbox';
9
9
  export { default as CKBoxEditing } from './ckboxediting';
10
10
  export { default as CKBoxUI } from './ckboxui';
11
+ export { default as CKBoxImageEditEditing } from './ckboximageedit/ckboximageeditediting';
12
+ export { default as CKBoxImageEditUI } from './ckboximageedit/ckboximageeditui';
13
+ export { default as CKBoxImageEdit } from './ckboximageedit';
11
14
  export type { default as CKBoxCommand } from './ckboxcommand';
15
+ export type { default as CKBoxImageEditCommand } from './ckboximageedit/ckboximageeditcommand';
12
16
  export type { CKBoxConfig } from './ckboxconfig';
13
17
  import './augmentation';
package/src/index.js CHANGED
@@ -8,4 +8,7 @@
8
8
  export { default as CKBox } from './ckbox';
9
9
  export { default as CKBoxEditing } from './ckboxediting';
10
10
  export { default as CKBoxUI } from './ckboxui';
11
+ export { default as CKBoxImageEditEditing } from './ckboximageedit/ckboximageeditediting';
12
+ export { default as CKBoxImageEditUI } from './ckboximageedit/ckboximageeditui';
13
+ export { default as CKBoxImageEdit } from './ckboximageedit';
11
14
  import './augmentation';
package/src/utils.d.ts CHANGED
@@ -30,3 +30,20 @@ export declare function getWorkspaceId(token: InitializedToken, defaultWorkspace
30
30
  * Generates an image data URL from its `blurhash` representation.
31
31
  */
32
32
  export declare function blurHashToDataUrl(hash?: string): string | undefined;
33
+ /**
34
+ * Sends the HTTP request.
35
+ *
36
+ * @internal
37
+ * @param config.url the URL where the request will be sent.
38
+ * @param config.method The HTTP method.
39
+ * @param config.data Additional data to send.
40
+ * @param config.onUploadProgress A callback informing about the upload progress.
41
+ */
42
+ export declare function sendHttpRequest({ url, method, data, onUploadProgress, signal, authorization }: {
43
+ url: URL;
44
+ signal: AbortSignal;
45
+ authorization: string;
46
+ method?: 'GET' | 'POST';
47
+ data?: FormData | null;
48
+ onUploadProgress?: (evt: ProgressEvent) => void;
49
+ }): Promise<any>;
package/src/utils.js CHANGED
@@ -80,3 +80,54 @@ export function blurHashToDataUrl(hash) {
80
80
  return undefined;
81
81
  }
82
82
  }
83
+ /**
84
+ * Sends the HTTP request.
85
+ *
86
+ * @internal
87
+ * @param config.url the URL where the request will be sent.
88
+ * @param config.method The HTTP method.
89
+ * @param config.data Additional data to send.
90
+ * @param config.onUploadProgress A callback informing about the upload progress.
91
+ */
92
+ export function sendHttpRequest({ url, method = 'GET', data, onUploadProgress, signal, authorization }) {
93
+ const xhr = new XMLHttpRequest();
94
+ xhr.open(method, url.toString());
95
+ xhr.setRequestHeader('Authorization', authorization);
96
+ xhr.setRequestHeader('CKBox-Version', 'CKEditor 5');
97
+ xhr.responseType = 'json';
98
+ // The callback is attached to the `signal#abort` event.
99
+ const abortCallback = () => {
100
+ xhr.abort();
101
+ };
102
+ return new Promise((resolve, reject) => {
103
+ signal.throwIfAborted();
104
+ signal.addEventListener('abort', abortCallback);
105
+ xhr.addEventListener('loadstart', () => {
106
+ signal.addEventListener('abort', abortCallback);
107
+ });
108
+ xhr.addEventListener('loadend', () => {
109
+ signal.removeEventListener('abort', abortCallback);
110
+ });
111
+ xhr.addEventListener('error', () => {
112
+ reject();
113
+ });
114
+ xhr.addEventListener('abort', () => {
115
+ reject();
116
+ });
117
+ xhr.addEventListener('load', () => {
118
+ const response = xhr.response;
119
+ if (!response || response.statusCode >= 400) {
120
+ return reject(response && response.message);
121
+ }
122
+ resolve(response);
123
+ });
124
+ /* istanbul ignore else -- @preserve */
125
+ if (onUploadProgress) {
126
+ xhr.upload.addEventListener('progress', evt => {
127
+ onUploadProgress(evt);
128
+ });
129
+ }
130
+ // Send the request.
131
+ xhr.send(data);
132
+ });
133
+ }
@@ -0,0 +1,53 @@
1
+ /*
2
+ * Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+
6
+ :root {
7
+ /* Based on default CKBox theme colors */
8
+ --ck-image-processing-highlight-color: hsl(220, 10%, 98%);
9
+ --ck-image-processing-background-color: hsl(220, 10%, 90%);
10
+ }
11
+
12
+ .ck.ck-editor__editable {
13
+ & .image {
14
+ &.image-processing {
15
+ position: relative;
16
+
17
+ &:before {
18
+ content: '';
19
+
20
+ position: absolute;
21
+ top: 0;
22
+ left: 0;
23
+ z-index: 1;
24
+
25
+ height: 100%;
26
+ width: 100%;
27
+
28
+ background: linear-gradient(
29
+ 90deg,
30
+ var(--ck-image-processing-background-color),
31
+ var(--ck-image-processing-highlight-color),
32
+ var(--ck-image-processing-background-color)
33
+ );
34
+ background-size: 200% 100%;
35
+
36
+ animation: ck-image-processing-animation 2s linear infinite;
37
+ }
38
+
39
+ & img {
40
+ height: 100%;
41
+ }
42
+ }
43
+ }
44
+ }
45
+
46
+ @keyframes ck-image-processing-animation {
47
+ 0% {
48
+ background-position: 200% 0;
49
+ }
50
+ 100% {
51
+ background-position: -200% 0;
52
+ }
53
+ }
@@ -0,0 +1 @@
1
+ <svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="M5.802 8.942a.607.607 0 0 0-.838-.029L1.429 12.8V3.158h12.93v5.25l1.429-1.319V2.758c0-.553-.467-1-1.039-1H1.05c-.582 0-1.049.447-1.049 1v11.281c0 .562.467 1.01 1.039 1.01h6.583v-.228c0-.124.052-.242.143-.326l4.504-4.157-.312-.367a.61.61 0 0 0-.829 0l-2.124 1.962-3.202-2.991Zm3.74-2.578a1.87 1.87 0 1 0 3.707-.486 1.87 1.87 0 0 0-3.707.486Z"/><path d="M8.874 15.926v2.316h2.317l6.836-6.834-2.32-2.32-6.833 6.84v-.002Zm10.944-6.312a.612.612 0 0 0 0-.87L18.372 7.3a.614.614 0 0 0-.87 0l-1.133 1.128 2.32 2.319 1.13-1.133Z"/></svg>