@ckeditor/ckeditor5-editor-multi-root 0.0.0-nightly-20231105.0 → 0.0.0-nightly-20231107.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md CHANGED
@@ -2,7 +2,7 @@ Software License Agreement
2
2
  ==========================
3
3
 
4
4
  **Multi-root editor implementation** – https://github.com/ckeditor/ckeditor5-editor-multi-root <br>
5
- Copyright (c) 2003-2023, [CKSource Holding sp. z o.o.](https://cksource.com) All rights reserved.
5
+ Copyright (c) 20032023, [CKSource Holding sp. z o.o.](https://cksource.com) All rights reserved.
6
6
 
7
7
  Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html).
8
8
 
@@ -13,9 +13,9 @@ Where not otherwise indicated, all CKEditor content is authored by CKSource engi
13
13
 
14
14
  The following libraries are included in CKEditor under the [MIT license](https://opensource.org/licenses/MIT):
15
15
 
16
- * lodash - Copyright (c) JS Foundation and other contributors https://js.foundation/. Based on Underscore.js, copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors http://underscorejs.org/.
16
+ * Lodash - Copyright (c) JS Foundation and other contributors https://js.foundation/. Based on Underscore.js, copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors http://underscorejs.org/.
17
17
 
18
18
  Trademarks
19
19
  ----------
20
20
 
21
- **CKEditor** is a trademark of [CKSource Holding sp. z o.o.](https://cksource.com) All other brand and product names are trademarks, registered trademarks or service marks of their respective holders.
21
+ **CKEditor** is a trademark of [CKSource Holding sp. z o.o.](https://cksource.com) All other brand and product names are trademarks, registered trademarks, or service marks of their respective holders.
@@ -1,4 +1,4 @@
1
1
  /*!
2
2
  * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md.
4
- */(()=>{var t={704:(t,e,o)=>{t.exports=o(79)("./src/core.js")},492:(t,e,o)=>{t.exports=o(79)("./src/engine.js")},273:(t,e,o)=>{t.exports=o(79)("./src/ui.js")},209:(t,e,o)=>{t.exports=o(79)("./src/utils.js")},434:(t,e,o)=>{t.exports=o(79)("./src/watchdog.js")},79:t=>{"use strict";t.exports=CKEditor5.dll}},e={};function o(i){var s=e[i];if(void 0!==s)return s.exports;var r=e[i]={exports:{}};return t[i](r,r.exports,o),r.exports}o.d=(t,e)=>{for(var i in e)o.o(e,i)&&!o.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},o.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),o.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var i={};(()=>{"use strict";o.r(i),o.d(i,{MultiRootEditor:()=>D});var t=o(704),e=o(209),s=o(434),r=o(273),n=o(492);class a extends r.EditorUI{constructor(t,e){super(t),this.view=e,this._lastFocusedEditableElement=null}init(){this.view.render(),this.focusTracker.on("change:focusedElement",((t,e,o)=>{for(const t of Object.values(this.view.editables))o===t.element&&(this._lastFocusedEditableElement=t.element)})),this.focusTracker.on("change:isFocused",((t,e,o)=>{o||(this._lastFocusedEditableElement=null)}));for(const t of Object.values(this.view.editables))this.addEditable(t);this._initToolbar(),this.fire("ready")}addEditable(t,e){const o=t.element;this.editor.editing.view.attachDomRoot(o,t.name),this.setEditableElement(t.name,o),t.bind("isFocused").to(this.focusTracker,"isFocused",this.focusTracker,"focusedElement",((t,e)=>!!t&&(e===o||this._lastFocusedEditableElement===o))),this._initPlaceholder(t,e)}removeEditable(t){this.editor.editing.view.detachDomRoot(t.name),t.unbind("isFocused"),this.removeEditableElement(t.name)}destroy(){super.destroy();for(const t of Object.values(this.view.editables))this.removeEditable(t);this.view.destroy()}_initToolbar(){const t=this.editor,e=this.view;e.toolbar.fillFromConfig(t.config.get("toolbar"),this.componentFactory),this.addToolbar(e.toolbar)}_initPlaceholder(t,e){if(!e){const o=this.editor.config.get("placeholder");o&&(e="string"==typeof o?o:o[t.name])}const o=this.editor.editing.view,i=o.document.getRoot(t.name);e&&(i.placeholder=e),(0,n.enablePlaceholder)({view:o,element:i,isDirectHost:!1,keepOnFocus:!0})}}class d extends r.EditorUIView{constructor(t,e,o,i={}){super(t),this._editingView=e,this.toolbar=new r.ToolbarView(t,{shouldGroupWhenFull:i.shouldToolbarGroupWhenFull}),this.editables={};for(const t of o){const e=i.editableElements?i.editableElements[t]:void 0;this.createEditable(t,e)}this.editable=Object.values(this.editables)[0],this.toolbar.extendTemplate({attributes:{class:["ck-reset_all","ck-rounded-corners"],dir:t.uiLanguageDirection}})}createEditable(t,e){const o=this.locale.t,i=new r.InlineEditableUIView(this.locale,this._editingView,e,{label:t=>o("Rich Text Editor. Editing area: %0",t.name)});return this.editables[t]=i,i.name=t,this.isRendered&&this.registerChild(i),i}removeEditable(t){const e=this.editables[t];this.isRendered&&this.deregisterChild(e),delete this.editables[t],e.destroy()}render(){super.render(),this.registerChild(Object.values(this.editables)),this.registerChild(this.toolbar)}}const l=function(t){return null!=t&&"object"==typeof t};const c="object"==typeof global&&global&&global.Object===Object&&global;var h="object"==typeof self&&self&&self.Object===Object&&self;const u=(c||h||Function("return this")()).Symbol;var f=Object.prototype,m=f.hasOwnProperty,b=f.toString,g=u?u.toStringTag:void 0;const y=function(t){var e=m.call(t,g),o=t[g];try{t[g]=void 0;var i=!0}catch(t){}var s=b.call(t);return i&&(e?t[g]=o:delete t[g]),s};var E=Object.prototype.toString;const R=function(t){return E.call(t)};var v=u?u.toStringTag:void 0;const p=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":v&&v in Object(t)?y(t):R(t)};const w=function(t,e){return function(o){return t(e(o))}}(Object.getPrototypeOf,Object);var O=Function.prototype,j=Object.prototype,_=O.toString,C=j.hasOwnProperty,k=_.call(Object);const A=function(t){if(!l(t)||"[object Object]"!=p(t))return!1;var e=w(t);if(null===e)return!0;var o=C.call(e,"constructor")&&e.constructor;return"function"==typeof o&&o instanceof o&&_.call(o)==k};const x=function(t){return l(t)&&1===t.nodeType&&!A(t)};class D extends((0,t.DataApiMixin)(t.Editor)){constructor(o,i={}){const s=Object.keys(o),r=0===s.length||"string"==typeof o[s[0]];if(r&&void 0!==i.initialData&&Object.keys(i.initialData).length>0)throw new e.CKEditorError("editor-create-initial-data",null);if(super(i),this._registeredRootsAttributesKeys=new Set,this._readOnlyRootLocks=new Map,this.sourceElements=r?{}:o,void 0===this.config.get("initialData")){const t={};for(const i of s)t[i]=T(n=o[i])?(0,e.getDataFromElement)(n):n;this.config.set("initialData",t)}var n;if(!r)for(const e of s)(0,t.secureSourceElement)(this,o[e]);this.editing.view.document.roots.on("add",((t,e)=>{e.unbind("isReadOnly"),e.bind("isReadOnly").to(this.editing.view.document,"isReadOnly",(t=>t||this._readOnlyRootLocks.has(e.rootName))),e.on("change:isReadOnly",((t,o,i)=>{const s=this.editing.view.createRangeIn(e);for(const t of s.getItems())t.is("editableElement")&&(t.unbind("isReadOnly"),t.isReadOnly=i)}))}));for(const t of s)this.model.document.createRoot("$root",t);if(this.config.get("lazyRoots"))for(const t of this.config.get("lazyRoots")){this.model.document.createRoot("$root",t)._isLoaded=!1}if(this.config.get("rootsAttributes")){const t=this.config.get("rootsAttributes");for(const[o,i]of Object.entries(t)){if(!this.model.document.getRoot(o))throw new e.CKEditorError("multi-root-editor-root-attributes-no-root",null);for(const t of Object.keys(i))this._registeredRootsAttributesKeys.add(t)}this.data.on("init",(()=>{this.model.enqueueChange({isUndoable:!1},(e=>{for(const[o,i]of Object.entries(t)){const t=this.model.document.getRoot(o);for(const[o,s]of Object.entries(i))null!==s&&e.setAttribute(o,s,t)}}))}))}const l={shouldToolbarGroupWhenFull:!this.config.get("toolbar.shouldNotGroupWhenFull"),editableElements:r?void 0:o},c=new d(this.locale,this.editing.view,s,l);this.ui=new a(this,c),this.model.document.on("change:data",(()=>{const t=this.model.document.differ.getChangedRoots();for(const e of t){const t=this.model.document.getRoot(e.name);"detached"==e.state&&this.fire("detachRoot",t)}for(const e of t){const t=this.model.document.getRoot(e.name);"attached"==e.state&&this.fire("addRoot",t)}})),this.listenTo(this.model,"canEditAt",((t,[e])=>{if(!e)return;let o=!1;for(const t of e.getRanges()){const e=t.root;if(this._readOnlyRootLocks.has(e.rootName)){o=!0;break}}o&&(t.return=!1,t.stop())}),{priority:"high"}),this.decorate("loadRoot"),this.on("loadRoot",((t,[o])=>{const i=this.model.document.getRoot(o);if(!i)throw new e.CKEditorError("multi-root-editor-load-root-no-root",this,{rootName:o});i._isLoaded&&((0,e.logWarning)("multi-root-editor-load-root-already-loaded"),t.stop())}),{priority:"highest"})}destroy(){const t=this.config.get("updateSourceElementOnDestroy"),o={};for(const e of Object.keys(this.sourceElements))o[e]=t?this.getData({rootName:e}):"";return this.ui.destroy(),super.destroy().then((()=>{for(const t of Object.keys(this.sourceElements))(0,e.setDataInElement)(this.sourceElements[t],o[t])}))}addRoot(t,{data:e="",attributes:o={},elementName:i="$root",isUndoable:s=!1}={}){const r=this.data,n=this._registeredRootsAttributesKeys;function a(s){const a=s.addRoot(t,i);e&&s.insert(r.parse(e,a),a,0);for(const t of Object.keys(o))n.add(t),s.setAttribute(t,o[t],a)}s?this.model.change(a):this.model.enqueueChange({isUndoable:!1},a)}detachRoot(t,e=!1){e?this.model.change((e=>e.detachRoot(t))):this.model.enqueueChange({isUndoable:!1},(e=>e.detachRoot(t)))}createEditable(t,e){const o=this.ui.view.createEditable(t.rootName);return this.ui.addEditable(o,e),this.editing.view.forceRender(),o.element}detachEditable(t){const e=t.rootName,o=this.ui.view.editables[e];return this.ui.removeEditable(o),this.ui.view.removeEditable(e),o.element}loadRoot(t,{data:e="",attributes:o={}}={}){const i=this.model.document.getRoot(t);this.model.enqueueChange({isUndoable:!1},(t=>{e&&t.insert(this.data.parse(e,i),i,0);for(const e of Object.keys(o))this._registeredRootsAttributesKeys.add(e),t.setAttribute(e,o[e],i);i._isLoaded=!0,this.model.document.differ._bufferRootLoad(i)}))}getFullData(t){const e={};for(const o of this.model.document.getRootNames())e[o]=this.data.get({...t,rootName:o});return e}getRootsAttributes(){const t={};for(const e of this.model.document.getRootNames())t[e]=this.getRootAttributes(e);return t}getRootAttributes(t){const e={},o=this.model.document.getRoot(t);for(const t of this._registeredRootsAttributesKeys)e[t]=o.hasAttribute(t)?o.getAttribute(t):null;return e}disableRoot(t,o){if("$graveyard"==t)throw new e.CKEditorError("multi-root-editor-cannot-disable-graveyard-root",this);const i=this._readOnlyRootLocks.get(t);if(i)i.add(o);else{this._readOnlyRootLocks.set(t,new Set([o]));this.editing.view.document.getRoot(t).isReadOnly=!0,Array.from(this.commands.commands()).forEach((t=>t.affectsData&&t.refresh()))}}enableRoot(t,e){const o=this._readOnlyRootLocks.get(t);if(o&&o.has(e))if(1===o.size){this._readOnlyRootLocks.delete(t);this.editing.view.document.getRoot(t).isReadOnly=this.isReadOnly,Array.from(this.commands.commands()).forEach((t=>t.affectsData&&t.refresh()))}else o.delete(e)}static create(t,o={}){return new Promise((i=>{for(const o of Object.values(t))if(T(o)&&"TEXTAREA"===o.tagName)throw new e.CKEditorError("editor-wrong-element",null);const s=new this(t,o);i(s.initPlugins().then((()=>s.ui.init())).then((()=>(s._verifyRootsWithInitialData(),s.data.init(s.config.get("initialData"))))).then((()=>s.fire("ready"))).then((()=>s)))}))}_verifyRootsWithInitialData(){const t=this.config.get("initialData");for(const o of this.model.document.getRootNames())if(!(o in t))throw new e.CKEditorError("multi-root-editor-root-initial-data-mismatch",null);for(const o of Object.keys(t)){const t=this.model.document.getRoot(o);if(!t||!t.isAttached())throw new e.CKEditorError("multi-root-editor-root-initial-data-mismatch",null)}}}function T(t){return x(t)}D.Context=t.Context,D.EditorWatchdog=s.EditorWatchdog,D.ContextWatchdog=s.ContextWatchdog})(),(window.CKEditor5=window.CKEditor5||{}).editorMultiRoot=i})();
4
+ */(()=>{var t={704:(t,e,o)=>{t.exports=o(79)("./src/core.js")},492:(t,e,o)=>{t.exports=o(79)("./src/engine.js")},273:(t,e,o)=>{t.exports=o(79)("./src/ui.js")},209:(t,e,o)=>{t.exports=o(79)("./src/utils.js")},434:(t,e,o)=>{t.exports=o(79)("./src/watchdog.js")},79:t=>{"use strict";t.exports=CKEditor5.dll}},e={};function o(i){var s=e[i];if(void 0!==s)return s.exports;var r=e[i]={exports:{}};return t[i](r,r.exports,o),r.exports}o.d=(t,e)=>{for(var i in e)o.o(e,i)&&!o.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},o.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),o.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var i={};(()=>{"use strict";o.r(i),o.d(i,{MultiRootEditor:()=>D});var t=o(704),e=o(209),s=o(434),r=o(273),n=o(492);class a extends r.EditorUI{constructor(t,e){super(t),this.view=e,this._lastFocusedEditableElement=null}init(){this.view.render(),this.focusTracker.on("change:focusedElement",((t,e,o)=>{for(const t of Object.values(this.view.editables))o===t.element&&(this._lastFocusedEditableElement=t.element)})),this.focusTracker.on("change:isFocused",((t,e,o)=>{o||(this._lastFocusedEditableElement=null)}));for(const t of Object.values(this.view.editables))this.addEditable(t);this._initToolbar(),this.fire("ready")}addEditable(t,e){const o=t.element;this.editor.editing.view.attachDomRoot(o,t.name),this.setEditableElement(t.name,o),t.bind("isFocused").to(this.focusTracker,"isFocused",this.focusTracker,"focusedElement",((t,e)=>!!t&&(e===o||this._lastFocusedEditableElement===o))),this._initPlaceholder(t,e)}removeEditable(t){this.editor.editing.view.detachDomRoot(t.name),t.unbind("isFocused"),this.removeEditableElement(t.name)}destroy(){super.destroy();for(const t of Object.values(this.view.editables))this.removeEditable(t);this.view.destroy()}_initToolbar(){const t=this.editor,e=this.view;e.toolbar.fillFromConfig(t.config.get("toolbar"),this.componentFactory),this.addToolbar(e.toolbar)}_initPlaceholder(t,e){if(!e){const o=this.editor.config.get("placeholder");o&&(e="string"==typeof o?o:o[t.name])}const o=this.editor.editing.view,i=o.document.getRoot(t.name);e&&(i.placeholder=e),(0,n.enablePlaceholder)({view:o,element:i,isDirectHost:!1,keepOnFocus:!0})}}class d extends r.EditorUIView{constructor(t,e,o,i={}){super(t),this._editingView=e,this.toolbar=new r.ToolbarView(t,{shouldGroupWhenFull:i.shouldToolbarGroupWhenFull}),this.editables={};for(const t of o){const e=i.editableElements?i.editableElements[t]:void 0;this.createEditable(t,e)}this.editable=Object.values(this.editables)[0],this.toolbar.extendTemplate({attributes:{class:["ck-reset_all","ck-rounded-corners"],dir:t.uiLanguageDirection}})}createEditable(t,e){const o=this.locale.t,i=new r.InlineEditableUIView(this.locale,this._editingView,e,{label:t=>o("Rich Text Editor. Editing area: %0",t.name)});return this.editables[t]=i,i.name=t,this.isRendered&&this.registerChild(i),i}removeEditable(t){const e=this.editables[t];this.isRendered&&this.deregisterChild(e),delete this.editables[t],e.destroy()}render(){super.render(),this.registerChild(Object.values(this.editables)),this.registerChild(this.toolbar)}}const l=function(t){return null!=t&&"object"==typeof t};const c="object"==typeof global&&global&&global.Object===Object&&global;var h="object"==typeof self&&self&&self.Object===Object&&self;const u=(c||h||Function("return this")()).Symbol;var f=Object.prototype,b=f.hasOwnProperty,m=f.toString,g=u?u.toStringTag:void 0;const y=function(t){var e=b.call(t,g),o=t[g];try{t[g]=void 0;var i=!0}catch(t){}var s=m.call(t);return i&&(e?t[g]=o:delete t[g]),s};var R=Object.prototype.toString;const E=function(t){return R.call(t)};var v=u?u.toStringTag:void 0;const p=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":v&&v in Object(t)?y(t):E(t)};const w=function(t,e){return function(o){return t(e(o))}}(Object.getPrototypeOf,Object);var O=Function.prototype,j=Object.prototype,_=O.toString,A=j.hasOwnProperty,C=_.call(Object);const k=function(t){if(!l(t)||"[object Object]"!=p(t))return!1;var e=w(t);if(null===e)return!0;var o=A.call(e,"constructor")&&e.constructor;return"function"==typeof o&&o instanceof o&&_.call(o)==C};const x=function(t){return l(t)&&1===t.nodeType&&!k(t)};class D extends((0,t.DataApiMixin)(t.Editor)){constructor(o,i={}){const s=Object.keys(o),r=0===s.length||"string"==typeof o[s[0]];if(r&&void 0!==i.initialData&&Object.keys(i.initialData).length>0)throw new e.CKEditorError("editor-create-initial-data",null);if(super(i),this._registeredRootsAttributesKeys=new Set,this._readOnlyRootLocks=new Map,this.sourceElements=r?{}:o,void 0===this.config.get("initialData")){const t={};for(const i of s)t[i]=T(n=o[i])?(0,e.getDataFromElement)(n):n;this.config.set("initialData",t)}var n;if(!r)for(const e of s)(0,t.secureSourceElement)(this,o[e]);this.editing.view.document.roots.on("add",((t,e)=>{e.unbind("isReadOnly"),e.bind("isReadOnly").to(this.editing.view.document,"isReadOnly",(t=>t||this._readOnlyRootLocks.has(e.rootName))),e.on("change:isReadOnly",((t,o,i)=>{const s=this.editing.view.createRangeIn(e);for(const t of s.getItems())t.is("editableElement")&&(t.unbind("isReadOnly"),t.isReadOnly=i)}))}));for(const t of s)this.model.document.createRoot("$root",t);if(this.config.get("lazyRoots"))for(const t of this.config.get("lazyRoots")){this.model.document.createRoot("$root",t)._isLoaded=!1}if(this.config.get("rootsAttributes")){const t=this.config.get("rootsAttributes");for(const[o,i]of Object.entries(t)){if(!this.model.document.getRoot(o))throw new e.CKEditorError("multi-root-editor-root-attributes-no-root",null);for(const t of Object.keys(i))this.registerRootAttribute(t)}this.data.on("init",(()=>{this.model.enqueueChange({isUndoable:!1},(e=>{for(const[o,i]of Object.entries(t)){const t=this.model.document.getRoot(o);for(const[o,s]of Object.entries(i))null!==s&&e.setAttribute(o,s,t)}}))}))}const l={shouldToolbarGroupWhenFull:!this.config.get("toolbar.shouldNotGroupWhenFull"),editableElements:r?void 0:o},c=new d(this.locale,this.editing.view,s,l);this.ui=new a(this,c),this.model.document.on("change:data",(()=>{const t=this.model.document.differ.getChangedRoots();for(const e of t){const t=this.model.document.getRoot(e.name);"detached"==e.state&&this.fire("detachRoot",t)}for(const e of t){const t=this.model.document.getRoot(e.name);"attached"==e.state&&this.fire("addRoot",t)}})),this.listenTo(this.model,"canEditAt",((t,[e])=>{if(!e)return;let o=!1;for(const t of e.getRanges()){const e=t.root;if(this._readOnlyRootLocks.has(e.rootName)){o=!0;break}}o&&(t.return=!1,t.stop())}),{priority:"high"}),this.decorate("loadRoot"),this.on("loadRoot",((t,[o])=>{const i=this.model.document.getRoot(o);if(!i)throw new e.CKEditorError("multi-root-editor-load-root-no-root",this,{rootName:o});i._isLoaded&&((0,e.logWarning)("multi-root-editor-load-root-already-loaded"),t.stop())}),{priority:"highest"})}destroy(){const t=this.config.get("updateSourceElementOnDestroy"),o={};for(const e of Object.keys(this.sourceElements))o[e]=t?this.getData({rootName:e}):"";return this.ui.destroy(),super.destroy().then((()=>{for(const t of Object.keys(this.sourceElements))(0,e.setDataInElement)(this.sourceElements[t],o[t])}))}addRoot(t,{data:e="",attributes:o={},elementName:i="$root",isUndoable:s=!1}={}){const r=s=>{const r=s.addRoot(t,i);e&&s.insert(this.data.parse(e,r),r,0);for(const t of Object.keys(o))this.registerRootAttribute(t),s.setAttribute(t,o[t],r)};s?this.model.change(r):this.model.enqueueChange({isUndoable:!1},r)}detachRoot(t,e=!1){e?this.model.change((e=>e.detachRoot(t))):this.model.enqueueChange({isUndoable:!1},(e=>e.detachRoot(t)))}createEditable(t,e){const o=this.ui.view.createEditable(t.rootName);return this.ui.addEditable(o,e),this.editing.view.forceRender(),o.element}detachEditable(t){const e=t.rootName,o=this.ui.view.editables[e];return this.ui.removeEditable(o),this.ui.view.removeEditable(e),o.element}loadRoot(t,{data:e="",attributes:o={}}={}){const i=this.model.document.getRoot(t);this.model.enqueueChange({isUndoable:!1},(t=>{e&&t.insert(this.data.parse(e,i),i,0);for(const e of Object.keys(o))this.registerRootAttribute(e),t.setAttribute(e,o[e],i);i._isLoaded=!0,this.model.document.differ._bufferRootLoad(i)}))}getFullData(t){const e={};for(const o of this.model.document.getRootNames())e[o]=this.data.get({...t,rootName:o});return e}getRootsAttributes(){const t={};for(const e of this.model.document.getRootNames())t[e]=this.getRootAttributes(e);return t}getRootAttributes(t){const e={},o=this.model.document.getRoot(t);for(const t of this._registeredRootsAttributesKeys)e[t]=o.hasAttribute(t)?o.getAttribute(t):null;return e}registerRootAttribute(t){this._registeredRootsAttributesKeys.has(t)||(this._registeredRootsAttributesKeys.add(t),this.editing.model.schema.extend("$root",{allowAttributes:t}))}disableRoot(t,o){if("$graveyard"==t)throw new e.CKEditorError("multi-root-editor-cannot-disable-graveyard-root",this);const i=this._readOnlyRootLocks.get(t);if(i)i.add(o);else{this._readOnlyRootLocks.set(t,new Set([o]));this.editing.view.document.getRoot(t).isReadOnly=!0,Array.from(this.commands.commands()).forEach((t=>t.affectsData&&t.refresh()))}}enableRoot(t,e){const o=this._readOnlyRootLocks.get(t);if(o&&o.has(e))if(1===o.size){this._readOnlyRootLocks.delete(t);this.editing.view.document.getRoot(t).isReadOnly=this.isReadOnly,Array.from(this.commands.commands()).forEach((t=>t.affectsData&&t.refresh()))}else o.delete(e)}static create(t,o={}){return new Promise((i=>{for(const o of Object.values(t))if(T(o)&&"TEXTAREA"===o.tagName)throw new e.CKEditorError("editor-wrong-element",null);const s=new this(t,o);i(s.initPlugins().then((()=>s.ui.init())).then((()=>(s._verifyRootsWithInitialData(),s.data.init(s.config.get("initialData"))))).then((()=>s.fire("ready"))).then((()=>s)))}))}_verifyRootsWithInitialData(){const t=this.config.get("initialData");for(const o of this.model.document.getRootNames())if(!(o in t))throw new e.CKEditorError("multi-root-editor-root-initial-data-mismatch",null);for(const o of Object.keys(t)){const t=this.model.document.getRoot(o);if(!t||!t.isAttached())throw new e.CKEditorError("multi-root-editor-root-initial-data-mismatch",null)}}}function T(t){return x(t)}D.Context=t.Context,D.EditorWatchdog=s.EditorWatchdog,D.ContextWatchdog=s.ContextWatchdog})(),(window.CKEditor5=window.CKEditor5||{}).editorMultiRoot=i})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-editor-multi-root",
3
- "version": "0.0.0-nightly-20231105.0",
3
+ "version": "0.0.0-nightly-20231107.0",
4
4
  "description": "Multi-root editor implementation for CKEditor 5.",
5
5
  "keywords": [
6
6
  "ckeditor",
@@ -11,7 +11,7 @@
11
11
  ],
12
12
  "main": "src/index.js",
13
13
  "dependencies": {
14
- "ckeditor5": "0.0.0-nightly-20231105.0",
14
+ "ckeditor5": "0.0.0-nightly-20231107.0",
15
15
  "lodash-es": "4.17.21"
16
16
  },
17
17
  "author": "CKSource (http://cksource.com/)",
@@ -144,9 +144,10 @@ export default class MultiRootEditor extends MultiRootEditor_base {
144
144
  * editor.addRoot( 'myRoot', { attributes: { isCollapsed: true, index: 4 } } );
145
145
  * ```
146
146
  *
147
- * See also {@link module:core/editor/editorconfig~EditorConfig#rootsAttributes `rootsAttributes` configuration option}.
147
+ * Note that attributes added together with a root are automatically registered.
148
148
  *
149
- * Note that attributes keys of attributes added in `attributes` option are also included in {@link #getRootsAttributes} return value.
149
+ * See also {@link ~#registerRootAttribute `MultiRootEditor#registerRootAttribute()`} and
150
+ * {@link module:core/editor/editorconfig~EditorConfig#rootsAttributes `config.rootsAttributes` configuration option}.
150
151
  *
151
152
  * By setting `isUndoable` flag to `true`, you can allow for detaching the root using the undo feature.
152
153
  *
@@ -257,6 +258,11 @@ export default class MultiRootEditor extends MultiRootEditor_base {
257
258
  *
258
259
  * This method is {@link module:utils/observablemixin~Observable#decorate decorated}.
259
260
  *
261
+ * Note that attributes loaded together with a root are automatically registered.
262
+ *
263
+ * See also {@link ~#registerRootAttribute `MultiRootEditor#registerRootAttribute()`} and
264
+ * {@link module:core/editor/editorconfig~EditorConfig#rootsAttributes `config.rootsAttributes` configuration option}.
265
+ *
260
266
  * When this method is used in real-time collaboration environment, its effects become asynchronous as the editor will first synchronize
261
267
  * with the remote editing session, before the root is added to the editor.
262
268
  *
@@ -281,8 +287,8 @@ export default class MultiRootEditor extends MultiRootEditor_base {
281
287
  /**
282
288
  * Returns attributes for all attached roots.
283
289
  *
284
- * Note: only attributes specified in {@link module:core/editor/editorconfig~EditorConfig#rootsAttributes `rootsAttributes`}
285
- * configuration option will be returned.
290
+ * Note: all and only {@link ~#registerRootAttribute registered} roots attributes will be returned. If a registered root attribute
291
+ * is not set for a given root, `null` will be returned.
286
292
  *
287
293
  * @returns Object with roots attributes. Keys are roots names, while values are attributes set on given root.
288
294
  */
@@ -290,12 +296,20 @@ export default class MultiRootEditor extends MultiRootEditor_base {
290
296
  /**
291
297
  * Returns attributes for the specified root.
292
298
  *
293
- * Note: only attributes specified in {@link module:core/editor/editorconfig~EditorConfig#rootsAttributes `rootsAttributes`}
294
- * configuration option will be returned.
295
- *
296
- * @param rootName
299
+ * Note: all and only {@link ~#registerRootAttribute registered} roots attributes will be returned. If a registered root attribute
300
+ * is not set for a given root, `null` will be returned.
297
301
  */
298
302
  getRootAttributes(rootName: string): RootAttributes;
303
+ /**
304
+ * Registers given string as a root attribute key. Registered root attributes are added to
305
+ * {@link module:engine/model/schema~Schema schema}, and also returned by
306
+ * {@link ~#getRootAttributes `getRootAttributes()`} and {@link ~#getRootsAttributes `getRootsAttributes()`}.
307
+ *
308
+ * Note: attributes passed in {@link module:core/editor/editorconfig~EditorConfig#rootsAttributes `config.rootsAttributes`} are
309
+ * automatically registered as the editor is initialized. However, registering the same attribute twice does not have any negative
310
+ * impact, so it is recommended to use this method in any feature that uses roots attributes.
311
+ */
312
+ registerRootAttribute(key: string): void;
299
313
  /**
300
314
  * Switches given editor root to the read-only mode.
301
315
  *
@@ -134,7 +134,7 @@ export default class MultiRootEditor extends DataApiMixin(Editor) {
134
134
  throw new CKEditorError('multi-root-editor-root-attributes-no-root', null);
135
135
  }
136
136
  for (const key of Object.keys(attributes)) {
137
- this._registeredRootsAttributesKeys.add(key);
137
+ this.registerRootAttribute(key);
138
138
  }
139
139
  }
140
140
  this.data.on('init', () => {
@@ -307,9 +307,10 @@ export default class MultiRootEditor extends DataApiMixin(Editor) {
307
307
  * editor.addRoot( 'myRoot', { attributes: { isCollapsed: true, index: 4 } } );
308
308
  * ```
309
309
  *
310
- * See also {@link module:core/editor/editorconfig~EditorConfig#rootsAttributes `rootsAttributes` configuration option}.
310
+ * Note that attributes added together with a root are automatically registered.
311
311
  *
312
- * Note that attributes keys of attributes added in `attributes` option are also included in {@link #getRootsAttributes} return value.
312
+ * See also {@link ~#registerRootAttribute `MultiRootEditor#registerRootAttribute()`} and
313
+ * {@link module:core/editor/editorconfig~EditorConfig#rootsAttributes `config.rootsAttributes` configuration option}.
313
314
  *
314
315
  * By setting `isUndoable` flag to `true`, you can allow for detaching the root using the undo feature.
315
316
  *
@@ -332,23 +333,21 @@ export default class MultiRootEditor extends DataApiMixin(Editor) {
332
333
  * @param options Additional options for the added root.
333
334
  */
334
335
  addRoot(rootName, { data = '', attributes = {}, elementName = '$root', isUndoable = false } = {}) {
335
- const dataController = this.data;
336
- const registeredKeys = this._registeredRootsAttributesKeys;
337
- if (isUndoable) {
338
- this.model.change(_addRoot);
339
- }
340
- else {
341
- this.model.enqueueChange({ isUndoable: false }, _addRoot);
342
- }
343
- function _addRoot(writer) {
336
+ const _addRoot = (writer) => {
344
337
  const root = writer.addRoot(rootName, elementName);
345
338
  if (data) {
346
- writer.insert(dataController.parse(data, root), root, 0);
339
+ writer.insert(this.data.parse(data, root), root, 0);
347
340
  }
348
341
  for (const key of Object.keys(attributes)) {
349
- registeredKeys.add(key);
342
+ this.registerRootAttribute(key);
350
343
  writer.setAttribute(key, attributes[key], root);
351
344
  }
345
+ };
346
+ if (isUndoable) {
347
+ this.model.change(_addRoot);
348
+ }
349
+ else {
350
+ this.model.enqueueChange({ isUndoable: false }, _addRoot);
352
351
  }
353
352
  }
354
353
  /**
@@ -457,6 +456,11 @@ export default class MultiRootEditor extends DataApiMixin(Editor) {
457
456
  *
458
457
  * This method is {@link module:utils/observablemixin~Observable#decorate decorated}.
459
458
  *
459
+ * Note that attributes loaded together with a root are automatically registered.
460
+ *
461
+ * See also {@link ~#registerRootAttribute `MultiRootEditor#registerRootAttribute()`} and
462
+ * {@link module:core/editor/editorconfig~EditorConfig#rootsAttributes `config.rootsAttributes` configuration option}.
463
+ *
460
464
  * When this method is used in real-time collaboration environment, its effects become asynchronous as the editor will first synchronize
461
465
  * with the remote editing session, before the root is added to the editor.
462
466
  *
@@ -474,7 +478,7 @@ export default class MultiRootEditor extends DataApiMixin(Editor) {
474
478
  writer.insert(this.data.parse(data, root), root, 0);
475
479
  }
476
480
  for (const key of Object.keys(attributes)) {
477
- this._registeredRootsAttributesKeys.add(key);
481
+ this.registerRootAttribute(key);
478
482
  writer.setAttribute(key, attributes[key], root);
479
483
  }
480
484
  root._isLoaded = true;
@@ -501,8 +505,8 @@ export default class MultiRootEditor extends DataApiMixin(Editor) {
501
505
  /**
502
506
  * Returns attributes for all attached roots.
503
507
  *
504
- * Note: only attributes specified in {@link module:core/editor/editorconfig~EditorConfig#rootsAttributes `rootsAttributes`}
505
- * configuration option will be returned.
508
+ * Note: all and only {@link ~#registerRootAttribute registered} roots attributes will be returned. If a registered root attribute
509
+ * is not set for a given root, `null` will be returned.
506
510
  *
507
511
  * @returns Object with roots attributes. Keys are roots names, while values are attributes set on given root.
508
512
  */
@@ -516,10 +520,8 @@ export default class MultiRootEditor extends DataApiMixin(Editor) {
516
520
  /**
517
521
  * Returns attributes for the specified root.
518
522
  *
519
- * Note: only attributes specified in {@link module:core/editor/editorconfig~EditorConfig#rootsAttributes `rootsAttributes`}
520
- * configuration option will be returned.
521
- *
522
- * @param rootName
523
+ * Note: all and only {@link ~#registerRootAttribute registered} roots attributes will be returned. If a registered root attribute
524
+ * is not set for a given root, `null` will be returned.
523
525
  */
524
526
  getRootAttributes(rootName) {
525
527
  const rootAttributes = {};
@@ -529,6 +531,22 @@ export default class MultiRootEditor extends DataApiMixin(Editor) {
529
531
  }
530
532
  return rootAttributes;
531
533
  }
534
+ /**
535
+ * Registers given string as a root attribute key. Registered root attributes are added to
536
+ * {@link module:engine/model/schema~Schema schema}, and also returned by
537
+ * {@link ~#getRootAttributes `getRootAttributes()`} and {@link ~#getRootsAttributes `getRootsAttributes()`}.
538
+ *
539
+ * Note: attributes passed in {@link module:core/editor/editorconfig~EditorConfig#rootsAttributes `config.rootsAttributes`} are
540
+ * automatically registered as the editor is initialized. However, registering the same attribute twice does not have any negative
541
+ * impact, so it is recommended to use this method in any feature that uses roots attributes.
542
+ */
543
+ registerRootAttribute(key) {
544
+ if (this._registeredRootsAttributesKeys.has(key)) {
545
+ return;
546
+ }
547
+ this._registeredRootsAttributesKeys.add(key);
548
+ this.editing.model.schema.extend('$root', { allowAttributes: key });
549
+ }
532
550
  /**
533
551
  * Switches given editor root to the read-only mode.
534
552
  *