From 296d0221346bda4451ea168925e4c80c87afed4f Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Mon, 5 Aug 2024 12:46:19 -0700
Subject: [PATCH 01/33] Navigation module integration

---
 MAINTENANCE.md                                |    2 +-
 assets/pencil-cursor.svg                      |    1 +
 assets/pencil-icon.svg                        |   16 +
 assets/pencil.svg                             |    1 +
 assets/vendor/ckeditor5/editor-inline.js      |    4 +-
 edit_plus.libraries.yml                       |    2 +
 edit_plus.module                              |   59 +-
 edit_plus.routing.yml                         |    1 +
 edit_plus.services.yml                        |    5 -
 js/edit-plus.js                               |   65 +-
 js/edit_plus/editable-element.js              |   10 +-
 js/edit_plus/entity-form.js                   |   16 +-
 .../fields/entity-reference-autocomplete.js   |    2 +-
 js/edit_plus/fields/inline-editor.js          |    4 +-
 js/edit_plus/fields/media.js                  |    2 +-
 .../src/EditPlusLbTempstoreRepository.php     |   31 +-
 package-lock.json                             | 1704 +++++++++++++++--
 package.json                                  |    2 +-
 .../MultipleEntityFormController.php          |    1 -
 src/Drush/Commands/UpdateInlineEditor.php     |    4 +-
 src/EditPlusFormTrait.php                     |    6 +-
 src/EditPlusMessagesTrait.php                 |    2 +
 src/EventSubscriber/CloneFieldAttribute.php   |   23 +-
 .../DefaultFieldAttributes.php                |    2 +-
 src/EventSubscriber/EntityTemplate.php        |   44 -
 .../InlineEditorFieldAttributes.php           |   11 +-
 src/EventSubscriber/MediaFieldAttributes.php  |   13 +-
 src/Form/InlineEntityFormAlter.php            |    3 +-
 src/ParamConverter/EntityConverter.php        |    1 -
 src/Plugin/Tool/EditPlus.php                  |    9 +-
 src/Plugin/Tool/edit-plus.js                  |   19 +
 yarn.lock                                     |  922 +++++++--
 32 files changed, 2417 insertions(+), 570 deletions(-)
 create mode 100644 assets/pencil-cursor.svg
 create mode 100644 assets/pencil-icon.svg
 create mode 100644 assets/pencil.svg
 delete mode 100644 src/EventSubscriber/EntityTemplate.php
 create mode 100644 src/Plugin/Tool/edit-plus.js

diff --git a/MAINTENANCE.md b/MAINTENANCE.md
index d79e05a..1f486a9 100644
--- a/MAINTENANCE.md
+++ b/MAINTENANCE.md
@@ -1,2 +1,2 @@
 # Edit+ Maintenanc
-Edit+ includes [CKEditors Inline Editor](https://ckeditor.com/docs/ckeditor5/latest/examples/builds/inline-editor.html). Update the library to match Drupal Core's version by running `yarn vender-update`
+Edit+ includes [CKEditors Inline Editor](https://ckeditor.com/docs/ckeditor5/latest/examples/builds/inline-editor.html). Update the library to match Drupal Core's version by running `yarn vendor-update`
diff --git a/assets/pencil-cursor.svg b/assets/pencil-cursor.svg
new file mode 100644
index 0000000..ef98c02
--- /dev/null
+++ b/assets/pencil-cursor.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path transform="rotate(90, 120, 120)" d="M227.31,73.37,182.63,28.68a16,16,0,0,0-22.63,0L36.69,152A15.86,15.86,0,0,0,32,163.31V208a16,16,0,0,0,16,16H92.69A15.86,15.86,0,0,0,104,219.31L227.31,96a16,16,0,0,0,0-22.63ZM192,108.68,147.31,64l24-24L216,84.68Z"></path></svg>
diff --git a/assets/pencil-icon.svg b/assets/pencil-icon.svg
new file mode 100644
index 0000000..818aa2b
--- /dev/null
+++ b/assets/pencil-icon.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg id="Layer_7" data-name="Layer 7" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 34.78 43.96">
+  <defs>
+    <style>
+      .cls-1 {
+        fill: none;
+        stroke: #000;
+        stroke-miterlimit: 13.48;
+        stroke-width: 1.48px;
+      }
+    </style>
+  </defs>
+  <polyline class="cls-1" points="12.87 21.38 12.04 17 15.91 19.22"/>
+  <rect class="cls-1" x="15.96" y="19.53" width="3.6" height="10.97" transform="translate(-11.23 14.96) rotate(-35.5)"/>
+  <rect class="cls-1" x="19.9" y="29.25" width="3.6" height="2.57" transform="translate(-13.7 18.27) rotate(-35.5)"/>
+</svg>
\ No newline at end of file
diff --git a/assets/pencil.svg b/assets/pencil.svg
new file mode 100644
index 0000000..278113c
--- /dev/null
+++ b/assets/pencil.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 256 256"><path fill="currentColor" d="M227.31,73.37,182.63,28.68a16,16,0,0,0-22.63,0L36.69,152A15.86,15.86,0,0,0,32,163.31V208a16,16,0,0,0,16,16H92.69A15.86,15.86,0,0,0,104,219.31L227.31,96a16,16,0,0,0,0-22.63ZM51.31,160,136,75.31,152.69,92,68,176.68ZM48,179.31,76.69,208H48Zm48,25.38L79.31,188,164,103.31,180.69,120Zm96-96L147.31,64l24-24L216,84.68Z"></path></svg>
diff --git a/assets/vendor/ckeditor5/editor-inline.js b/assets/vendor/ckeditor5/editor-inline.js
index 3bd7334..8d28d50 100644
--- a/assets/vendor/ckeditor5/editor-inline.js
+++ b/assets/vendor/ckeditor5/editor-inline.js
@@ -1,4 +1,4 @@
 /*!
- * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
  * For licensing, see LICENSE.md.
- */(()=>{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 r=e[i];if(void 0!==r)return r.exports;var n=e[i]={exports:{}};return t[i](n,n.exports,o),n.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,{InlineEditor:()=>D});var t=o(704),e=o(209),r=o(434),n=o(273),s=o(492);class l extends n.EditorUI{constructor(t,e){super(t),this.view=e,this._toolbarConfig=(0,n.normalizeToolbarConfig)(t.config.get("toolbar"))}get element(){return this.view.editable.element}init(){const t=this.editor,e=this.view,o=t.editing.view,i=e.editable,r=o.document.getRoot();i.name=r.rootName,e.render();const n=i.element;this.setEditableElement(i.name,n),i.bind("isFocused").to(this.focusTracker),o.attachDomRoot(n),this._initPlaceholder(),this._initToolbar(),this.fire("ready")}destroy(){super.destroy();const t=this.view;this.editor.editing.view.detachDomRoot(t.editable.name),t.destroy()}_initToolbar(){const t=this.editor,e=this.view,o=e.editable.element,i=e.toolbar;e.panel.bind("isVisible").to(this.focusTracker,"isFocused"),e.bind("viewportTopOffset").to(this,"viewportOffset",(({top:t})=>t||0)),e.listenTo(t.ui,"update",(()=>{e.panel.isVisible&&e.panel.pin({target:o,positions:e.panelPositions})})),i.fillFromConfig(this._toolbarConfig,this.componentFactory),this.addToolbar(i)}_initPlaceholder(){const t=this.editor,e=t.editing.view,o=e.document.getRoot(),i=t.config.get("placeholder");if(i){const t="string"==typeof i?i:i[o.rootName];t&&(o.placeholder=t)}(0,s.enablePlaceholder)({view:e,element:o,isDirectHost:!1,keepOnFocus:!0})}}const a=(0,e.toUnit)("px");class c extends n.EditorUIView{constructor(t,e,o,i={}){super(t);const r=t.t;this.toolbar=new n.ToolbarView(t,{shouldGroupWhenFull:i.shouldToolbarGroupWhenFull,isFloating:!0}),this.set("viewportTopOffset",0),this.panel=new n.BalloonPanelView(t),this.panelPositions=this._getPanelPositions(),this.panel.extendTemplate({attributes:{class:"ck-toolbar-container"}}),this.editable=new n.InlineEditableUIView(t,e,o,{label:t=>r("Rich Text Editor. Editing area: %0",t.name)}),this._resizeObserver=null}render(){super.render(),this.body.add(this.panel),this.registerChild(this.editable),this.panel.content.add(this.toolbar);if(this.toolbar.options.shouldGroupWhenFull){const t=this.editable.element;this._resizeObserver=new e.ResizeObserver(t,(()=>{this.toolbar.maxWidth=a(new e.Rect(t).width)}))}}destroy(){super.destroy(),this._resizeObserver&&this._resizeObserver.destroy()}_getPanelPositionTop(t,e){let o;return o=t.top>e.height+this.viewportTopOffset?t.top-e.height:t.bottom>e.height+this.viewportTopOffset+50?this.viewportTopOffset:t.bottom,o}_getPanelPositions(){const t=[(t,e)=>({top:this._getPanelPositionTop(t,e),left:t.left,name:"toolbar_west",config:{withArrow:!1}}),(t,e)=>({top:this._getPanelPositionTop(t,e),left:t.left+t.width-e.width,name:"toolbar_east",config:{withArrow:!1}})];return"ltr"===this.locale.uiLanguageDirection?t:t.reverse()}}const d=function(t){return null!=t&&"object"==typeof t};const h="object"==typeof global&&global&&global.Object===Object&&global;var u="object"==typeof self&&self&&self.Object===Object&&self;const p=(h||u||Function("return this")()).Symbol;var b=Object.prototype,f=b.hasOwnProperty,g=b.toString,w=p?p.toStringTag:void 0;const v=function(t){var e=f.call(t,w),o=t[w];try{t[w]=void 0;var i=!0}catch(t){}var r=g.call(t);return i&&(e?t[w]=o:delete t[w]),r};var m=Object.prototype.toString;const y=function(t){return m.call(t)};var O=p?p.toStringTag:void 0;const T=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":O&&O in Object(t)?v(t):y(t)};const j=function(t,e){return function(o){return t(e(o))}}(Object.getPrototypeOf,Object);var E=Function.prototype,P=Object.prototype,x=E.toString,_=P.hasOwnProperty,F=x.call(Object);const C=function(t){if(!d(t)||"[object Object]"!=T(t))return!1;var e=j(t);if(null===e)return!0;var o=_.call(e,"constructor")&&e.constructor;return"function"==typeof o&&o instanceof o&&x.call(o)==F};const S=function(t){return d(t)&&1===t.nodeType&&!C(t)};class D extends((0,t.DataApiMixin)((0,t.ElementApiMixin)(t.Editor))){constructor(o,i={}){if(!W(o)&&void 0!==i.initialData)throw new e.CKEditorError("editor-create-initial-data",null);super(i),void 0===this.config.get("initialData")&&this.config.set("initialData",function(t){return W(t)?(0,e.getDataFromElement)(t):t}(o)),this.model.document.createRoot(),W(o)&&(this.sourceElement=o,(0,t.secureSourceElement)(this,o));const r=!this.config.get("toolbar.shouldNotGroupWhenFull"),n=new c(this.locale,this.editing.view,this.sourceElement,{shouldToolbarGroupWhenFull:r});this.ui=new l(this,n),(0,t.attachToForm)(this)}destroy(){const t=this.getData();return this.ui.destroy(),super.destroy().then((()=>{this.sourceElement&&this.updateSourceElement(t)}))}static create(t,o={}){return new Promise((i=>{if(W(t)&&"TEXTAREA"===t.tagName)throw new e.CKEditorError("editor-wrong-element",null);const r=new this(t,o);i(r.initPlugins().then((()=>r.ui.init())).then((()=>r.data.init(r.config.get("initialData")))).then((()=>r.fire("ready"))).then((()=>r)))}))}}function W(t){return S(t)}D.Context=t.Context,D.EditorWatchdog=r.EditorWatchdog,D.ContextWatchdog=r.ContextWatchdog})(),(window.CKEditor5=window.CKEditor5||{}).editorInline=i})();
\ No newline at end of file
+ */(()=>{var t={782:(t,e,o)=>{t.exports=o(237)("./src/core.js")},783:(t,e,o)=>{t.exports=o(237)("./src/engine.js")},311:(t,e,o)=>{t.exports=o(237)("./src/ui.js")},584:(t,e,o)=>{t.exports=o(237)("./src/utils.js")},237:t=>{"use strict";t.exports=CKEditor5.dll}},e={};function o(i){var r=e[i];if(void 0!==r)return r.exports;var n=e[i]={exports:{}};return t[i](n,n.exports,o),n.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,{InlineEditor:()=>C});var t=o(782),e=o(584),r=o(311),n=o(783);class s extends r.EditorUI{constructor(t,e){super(t),this.view=e,this._toolbarConfig=(0,r.normalizeToolbarConfig)(t.config.get("toolbar"))}get element(){return this.view.editable.element}init(){const t=this.editor,e=this.view,o=t.editing.view,i=e.editable,r=o.document.getRoot();i.name=r.rootName,e.render();const n=i.element;this.setEditableElement(i.name,n),i.bind("isFocused").to(this.focusTracker),o.attachDomRoot(n),this._initPlaceholder(),this._initToolbar(),this.fire("ready")}destroy(){super.destroy();const t=this.view;this.editor.editing.view.detachDomRoot(t.editable.name),t.destroy()}_initToolbar(){const t=this.editor,e=this.view,o=e.editable.element,i=e.toolbar;e.panel.bind("isVisible").to(this.focusTracker,"isFocused"),e.bind("viewportTopOffset").to(this,"viewportOffset",(({top:t})=>t||0)),e.listenTo(t.ui,"update",(()=>{e.panel.isVisible&&e.panel.pin({target:o,positions:e.panelPositions})})),i.fillFromConfig(this._toolbarConfig,this.componentFactory),this.addToolbar(i)}_initPlaceholder(){const t=this.editor,e=t.editing.view,o=e.document.getRoot(),i=t.config.get("placeholder");if(i){const t="string"==typeof i?i:i[o.rootName];t&&(o.placeholder=t)}(0,n.enablePlaceholder)({view:e,element:o,isDirectHost:!1,keepOnFocus:!0})}}const l=(0,e.toUnit)("px");class a extends r.EditorUIView{constructor(t,e,o,i={}){super(t);const n=t.t;this.toolbar=new r.ToolbarView(t,{shouldGroupWhenFull:i.shouldToolbarGroupWhenFull,isFloating:!0}),this.set("viewportTopOffset",0),this.panel=new r.BalloonPanelView(t),this.panelPositions=this._getPanelPositions(),this.panel.extendTemplate({attributes:{class:"ck-toolbar-container"}}),this.editable=new r.InlineEditableUIView(t,e,o,{label:t=>n("Rich Text Editor. Editing area: %0",t.name)}),this._resizeObserver=null}render(){super.render(),this.body.add(this.panel),this.registerChild(this.editable),this.panel.content.add(this.toolbar);if(this.toolbar.options.shouldGroupWhenFull){const t=this.editable.element;this._resizeObserver=new e.ResizeObserver(t,(()=>{this.toolbar.maxWidth=l(new e.Rect(t).width)}))}}destroy(){super.destroy(),this._resizeObserver&&this._resizeObserver.destroy()}_getPanelPositionTop(t,e){let o;return o=t.top>e.height+this.viewportTopOffset?t.top-e.height:t.bottom>e.height+this.viewportTopOffset+50?this.viewportTopOffset:t.bottom,o}_getPanelPositions(){const t=[(t,e)=>({top:this._getPanelPositionTop(t,e),left:t.left,name:"toolbar_west",config:{withArrow:!1}}),(t,e)=>({top:this._getPanelPositionTop(t,e),left:t.left+t.width-e.width,name:"toolbar_east",config:{withArrow:!1}})];return"ltr"===this.locale.uiLanguageDirection?t:t.reverse()}}const c=function(t){return null!=t&&"object"==typeof t};const d="object"==typeof global&&global&&global.Object===Object&&global;var h="object"==typeof self&&self&&self.Object===Object&&self;const u=(d||h||Function("return this")()).Symbol;var p=Object.prototype,b=p.hasOwnProperty,f=p.toString,g=u?u.toStringTag:void 0;const w=function(t){var e=b.call(t,g),o=t[g];try{t[g]=void 0;var i=!0}catch(t){}var r=f.call(t);return i&&(e?t[g]=o:delete t[g]),r};var v=Object.prototype.toString;const m=function(t){return v.call(t)};var y=u?u.toStringTag:void 0;const O=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":y&&y in Object(t)?w(t):m(t)};const T=function(t,e){return function(o){return t(e(o))}}(Object.getPrototypeOf,Object);var j=Function.prototype,E=Object.prototype,P=j.toString,_=E.hasOwnProperty,x=P.call(Object);const F=function(t){if(!c(t)||"[object Object]"!=O(t))return!1;var e=T(t);if(null===e)return!0;var o=_.call(e,"constructor")&&e.constructor;return"function"==typeof o&&o instanceof o&&P.call(o)==x};const S=function(t){return c(t)&&1===t.nodeType&&!F(t)};class C extends((0,t.ElementApiMixin)(t.Editor)){constructor(o,i={}){if(!D(o)&&void 0!==i.initialData)throw new e.CKEditorError("editor-create-initial-data",null);super(i),void 0===this.config.get("initialData")&&this.config.set("initialData",function(t){return D(t)?(0,e.getDataFromElement)(t):t}(o)),this.model.document.createRoot(),D(o)&&(this.sourceElement=o,(0,t.secureSourceElement)(this,o));const r=!this.config.get("toolbar.shouldNotGroupWhenFull"),n=new a(this.locale,this.editing.view,this.sourceElement,{shouldToolbarGroupWhenFull:r});this.ui=new s(this,n),(0,t.attachToForm)(this)}destroy(){const t=this.getData();return this.ui.destroy(),super.destroy().then((()=>{this.sourceElement&&this.updateSourceElement(t)}))}static create(t,o={}){return new Promise((i=>{if(D(t)&&"TEXTAREA"===t.tagName)throw new e.CKEditorError("editor-wrong-element",null);const r=new this(t,o);i(r.initPlugins().then((()=>r.ui.init())).then((()=>r.data.init(r.config.get("initialData")))).then((()=>r.fire("ready"))).then((()=>r)))}))}}function D(t){return S(t)}})(),(window.CKEditor5=window.CKEditor5||{}).editorInline=i})();
\ No newline at end of file
diff --git a/edit_plus.libraries.yml b/edit_plus.libraries.yml
index 983b2ab..719a71d 100644
--- a/edit_plus.libraries.yml
+++ b/edit_plus.libraries.yml
@@ -2,6 +2,7 @@ library:
   js:
     assets/vendor/ckeditor5/editor-inline.js: { minified: true }
     js/edit-plus.js: { attributes: { type: 'module' }}
+    src/Plugin/Tool/edit-plus.js: { attributes: { type: 'module' }}
   css:
     component:
       css/bottom-bar.css: {}
@@ -12,6 +13,7 @@ library:
     - core/jquery
     - core/ckeditor5
     - core/ckeditor5.basic
+    - toolbar_plus/toolbar_plus
     - core/ckeditor5.essentials
     - core/ckeditor5.autoformat
     - core/ckeditor5.htmlSupport
diff --git a/edit_plus.module b/edit_plus.module
index 49e7e99..bc88e93 100644
--- a/edit_plus.module
+++ b/edit_plus.module
@@ -8,10 +8,8 @@
 use Drupal\block_content\Entity\BlockContent;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Template\Attribute;
-use Drupal\edit_plus\Controller\MultipleEntityFormController;
 
 /**
  * Implements hook_page_attachments().
@@ -165,20 +163,6 @@ function template_preprocess_inline_textarea(&$variables) {
   $variables['inline_editor_attributes'] =  new Attribute(['class' => ['edit-plus-inline-edit']]);
 }
 
-/**
- * Implements hook_page_bottom().
- */
-function edit_plus_page_bottom(array &$page_bottom) {
-  $page_bottom['bottom_bar'] = [
-    '#type' => 'container',
-    '#attributes' => [
-      'id' => 'toolbar-plus-bottom-bar',
-    ],
-  ];
-
-  buildBottomBar($page_bottom);
-}
-
 // @todo This should tie into toolbar +.
 function buildBottomBar(array &$page_bottom) {
   $actively_used_tempstore_entities = edit_plus_active_tempstore_entities();
@@ -235,24 +219,9 @@ function edit_plus_element_info_alter(&$types) {
   $types['inline_textarea']['#pre_render'][] = 'element.edit_plus:preRenderTextFormat';
 }
 
-/**
- * Implements hook_entity_build_defaults_alter().
- */
-function edit_plus_entity_build_defaults_alter(array &$build, \Drupal\Core\Entity\EntityInterface $entity, $view_mode) {
-  // Flag that the entity needs a wrapper. This wrapper is used to update the page
-  // once an action happens. e.g. adding a new field to the page.
-  // @see EntityTemplate->onTwigRenderTemplate()
-  // @see EditPlusFormTrait->addEmptyField()
-  $build['#edit_plus_entity'] = [
-    'entity_type' => $entity->getEntityTypeId(),
-    'entity_id' => edit_plus_entity_identifier($entity),
-    'bundle' => $entity->bundle(),
-    'view_mode' => $view_mode,
-  ];
-}
-
 function edit_plus_entity_identifier(EntityInterface $entity) {
   // @todo Can we just use uuid for everything?
+  // @todo This is also duplicated as toolbar_plus_entity_identifier.
   return !$entity instanceof BlockContent ? $entity->id() : $entity->uuid();
 }
 
@@ -263,30 +232,4 @@ function edit_plus_form_field_config_edit_form_alter(&$form, FormStateInterface
   \Drupal::service('edit_plus.field_config_form_alter')->formAlter($form, $form_state);
 }
 
-/**
- * Find widget in form.
- *
- * @param array $form_item
- *   The form item to find the widget element for.
- * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
- *   The field definition.
- *
- * @return mixed
- *   The actual field widget form item.
- */
-function edit_plus_find_widget_type(array $form_item, FieldDefinitionInterface $field_definition) {
-  $property_name = $field_definition->getfieldstoragedefinition()->getmainpropertyname();
-  if (!empty($form_item['#theme']) && $form_item['#theme'] == 'inline_textarea') {
-    return 'inline_textarea';
-  }
-  // @todo Is there a better way to discern what the widget is???
-  $widget = $form_item['widget'][0] ?? $form_item['widget'][0][$property_name] ?? $form_item['widget'][$property_name] ?? $form_item['widget'] ?? $form_item[$property_name] ?? NULL;
-  if (!empty($widget['media_library_selection'])) {
-    return 'media_library';
-  }
-  if (!empty($widget['#type'])) {
-    return $widget['#type'];
-  }
-  return NULL;
-}
 
diff --git a/edit_plus.routing.yml b/edit_plus.routing.yml
index cf3a3a6..9abadd1 100644
--- a/edit_plus.routing.yml
+++ b/edit_plus.routing.yml
@@ -4,6 +4,7 @@ edit_plus.entity_form:
     _title: 'Entity Form'
     _controller: '\Drupal\edit_plus\Controller\MultipleEntityFormController::entityForm'
   options:
+    _admin_route: true
     parameters:
       entity:
         type: entity:{entity_type}
diff --git a/edit_plus.services.yml b/edit_plus.services.yml
index e000c2a..587ef0e 100644
--- a/edit_plus.services.yml
+++ b/edit_plus.services.yml
@@ -26,11 +26,6 @@ services:
   edit_plus.ui:
     class: Drupal\edit_plus\Ui
 
-  edit_plus.event_subscriber.entity_template:
-    class: Drupal\edit_plus\EventSubscriber\EntityTemplate
-    tags:
-      - { name: event_subscriber }
-
   edit_plus.event_subscriber.default_field_attributes:
     class: Drupal\edit_plus\EventSubscriber\DefaultFieldAttributes
     tags:
diff --git a/js/edit-plus.js b/js/edit-plus.js
index 25d43ab..38bdefe 100644
--- a/js/edit-plus.js
+++ b/js/edit-plus.js
@@ -2,7 +2,7 @@ import * as entityForm from './edit_plus/entity-form.js';
 import * as editableElement from './edit_plus/editable-element.js';
 import * as pluginManager from './edit_plus/field-plugin-manager.js';
 
-(($, Drupal, once) => {
+(($, Drupal, once, displace) => {
 
   Drupal.EditPlus = {};
   Drupal.EditPlus.EditMode = 'enabled';
@@ -71,11 +71,6 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
     once.remove('EditPlusDisabled', '.edit-plus-field-value', document);
     once('EditPlusEnabled', '.edit-plus-field-value', document).forEach(editableField => {
       editableField.addEventListener('mousedown', Drupal.EditPlus.EditableElementClicked);
-      // Temporarily reveal the sidebar here. // @todo move to toolbar+
-      const sidebar = document.querySelector('#toolbar-plus-sidebar');
-      if (sidebar.querySelector('.edit-plus-form')) {
-        sidebar.style.display = 'inherit';
-      }
     });
     Drupal.EditPlus.DisableInteractiveElements();
   }
@@ -83,34 +78,34 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
   /**
    * Disable edit mode
    */
-  Drupal.EditPlus.DisableEditMode = () => {
-    once.remove('EditPlusEnabled', '.edit-plus-field-value', document);
-    once('EditPlusDisabled', '.edit-plus-field-value', document).forEach(editableField => {
-      editableField.removeEventListener('mousedown', Drupal.EditPlus.EditableElementClicked);
+  Drupal.EditPlus.DisableEditMode = async () => {
+    await Drupal.EditPlus.notUpdating();
+    return new Promise((resolve, reject) => {
+      once.remove('EditPlusEnabled', '.edit-plus-field-value', document);
+      once('EditPlusDisabled', '.edit-plus-field-value', document).forEach(editableField => {
+        editableField.removeEventListener('mousedown', Drupal.EditPlus.EditableElementClicked);
+      });
+      document.querySelectorAll('.edit-plus-form.toolbar-plus-sidebar').forEach(sidebar => {
+        sidebar.classList.add('toolbar-plus-hidden');
+        sidebar.removeAttribute('data-offset-right');
+        displace();
+      });
+
+      Drupal.EditPlus.EnableInteractiveElements();
+      resolve();
     });
-    document.querySelector('#toolbar-plus-sidebar').style.display = 'none'; // @todo move to toolbar+
-    Drupal.EditPlus.EnableInteractiveElements();
   }
 
-  /**
-   * Toggle edit mode.
-   *
-   * This listens for toolbar_plus's toggleToolbarTool event.
-   */
-  Drupal.behaviors.EditPlusToggle = {
-    attach: (context, settings) => {
-      once('EditPlusToolbarToggle', 'html', context).forEach(element => {
-        // Toggle Edit+ on and off.
-        window.addEventListener('toggleToolbarTool', e => {
-          if (e.detail.tool === 'edit_plus' && e.detail.state === 'on') {
-            Drupal.EditPlus.EnableEditMode();
-          } else {
-            Drupal.EditPlus.DisableEditMode();
-          }
-        });
-      });
-    }
-  };
+  Drupal.EditPlus.notUpdating = () => {
+    return new Promise(resolve => {
+      const intervalId = setInterval(() => {
+        if (!entityForm.editPlusIsUpdating) {
+          clearInterval(intervalId);
+          resolve();
+        }
+      }, 100);
+    });
+  }
 
   /**
    * Edit + persist state.
@@ -120,7 +115,7 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
    */
   Drupal.behaviors.EditPlusPersistState = {
     attach: (context, settings) => {
-      once('EditPlusPersistState', '.edit-plus-entity-wrapper', context).forEach(element => {
+      once('EditPlusPersistState', '.toolbar-plus-entity-wrapper', context).forEach(element => {
         // Persist the state.
         if (
           sessionStorage.getItem('toolbarState') === 'open' &&
@@ -143,7 +138,7 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
     e.stopPropagation();
   };
   Drupal.EditPlus.DisableInteractiveElements = () => {
-    $('.edit-plus-entity-wrapper')
+    $('.toolbar-plus-entity-wrapper')
       .find('a')
       .each((index, link) => {
         // Disable clicking links while in edit mode.
@@ -152,7 +147,7 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
   };
 
   Drupal.EditPlus.EnableInteractiveElements = () => {
-    $('.edit-plus-entity-wrapper')
+    $('.toolbar-plus-entity-wrapper')
       .find('a')
       .each((index, link) => {
         // Enable clicking links when leaving edit mode.
@@ -160,7 +155,7 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
       });
   };
 
-})(jQuery, Drupal, once);
+})(jQuery, Drupal, once, Drupal.displace);
 
 
 
diff --git a/js/edit_plus/editable-element.js b/js/edit_plus/editable-element.js
index 03995b8..fe0a8b1 100644
--- a/js/edit_plus/editable-element.js
+++ b/js/edit_plus/editable-element.js
@@ -153,12 +153,16 @@ export class EditableElement {
    *   within a form item wrapper.
    */
   static createFromFormItem(element) {
+    let editableElement;
     const wrapper = element.closest('.edit-plus-form-item-wrapper');
     if (wrapper) {
-      return new EditableElement(wrapper.dataset.editPlusPageElementId);
+      editableElement = new EditableElement(wrapper.dataset.editPlusPageElementId);
+    } else {
+      const pageElement = document.querySelector('[data-edit-plus-markup-item-id="' + element.dataset.editPlusFormItemId + '"]');
+      editableElement = new EditableElement(pageElement.dataset.editPlusId);
     }
-    const pageElement = document.querySelector('[data-edit-plus-markup-item-id="' + element.dataset.editPlusFormItemId + '"]');
-    return new EditableElement(pageElement.dataset.editPlusId);
+    editableElement.setWidget();
+    return editableElement;
   }
 
 }
diff --git a/js/edit_plus/entity-form.js b/js/edit_plus/entity-form.js
index 2ad6281..b2aa589 100644
--- a/js/edit_plus/entity-form.js
+++ b/js/edit_plus/entity-form.js
@@ -13,13 +13,15 @@ import * as utilities from './utilities.js';
 export const getForm = (EditableElement) => {
   // Hide/cache previously loaded forms.
   document.querySelectorAll('.edit-plus-form').forEach(form => {
-    form.classList.add('edit-plus-hidden');
+    form.classList.add('toolbar-plus-hidden');
   });
   // Return the requested form if we already have it.
   const formExists = EditableElement.getForm();
   if (formExists) {
     return new Promise((resolve, reject) => {
-      formExists.classList.remove('edit-plus-hidden');
+      formExists.classList.remove('toolbar-plus-hidden');
+      formExists.setAttribute('data-offset-right', '');
+      Drupal.displace();
       resolve({status: 'existing_form'});
     });
   }
@@ -151,7 +153,6 @@ const getEntityForm = (EditableElement) => {
     EditableElement.info.ajaxReturnForm = false;
   });
 }
-
 // @todo I think we need to tag auto save items in the sidebar on the backend.
 // export const autosaveNonEditableElements = (EditableElement) => {
 //   EditableElement.getForm().querySelectorAll('[data-edit-plus-input]').forEach(input => {
@@ -163,13 +164,17 @@ const getEntityForm = (EditableElement) => {
 //         input.addEventListener('change', e => {
 //           const updateButton = input.closest('form').querySelector('.edit-plus-update-button');
 //           jQuery(updateButton).mousedown();
-//           editPlusIsUpdating = true;
 //         });
 //       }
 //     }
 //   });
 // }
 
+/**
+ * Flag that the page is currently being updated.
+ *
+ * @type {boolean}
+ */
 export let editPlusIsUpdating = false;
 
 /**
@@ -195,3 +200,6 @@ export const updateTempstore = (EditableElement, isEmpty) => {
   editPlusIsUpdating = true;
 }
 
+jQuery.fn.editPlusIsDoneUpdating = () => {
+  editPlusIsUpdating = false;
+}
diff --git a/js/edit_plus/fields/entity-reference-autocomplete.js b/js/edit_plus/fields/entity-reference-autocomplete.js
index f5a3dc0..6ee412d 100644
--- a/js/edit_plus/fields/entity-reference-autocomplete.js
+++ b/js/edit_plus/fields/entity-reference-autocomplete.js
@@ -7,7 +7,7 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
    */
   class EntityReferenceAutocompletePlugin extends defaultPlugin.DefaultPlugin {
 
-    supportedWidgets = ['entity_autocomplete'];
+    supportedWidgets = ['entity_reference_autocomplete_tags'];
 
     getFormItemInputs(EditableElement) {
       return EditableElement.getFormItemWrapper().querySelectorAll('input');
diff --git a/js/edit_plus/fields/inline-editor.js b/js/edit_plus/fields/inline-editor.js
index 60c125a..2555388 100644
--- a/js/edit_plus/fields/inline-editor.js
+++ b/js/edit_plus/fields/inline-editor.js
@@ -18,7 +18,7 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
      * @type {[string]}
      */
     supportedWidgets = [
-      'inline_textarea',
+      'text_textarea',
     ];
 
     /**
@@ -262,8 +262,8 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
             // Remember the editors original state.
             const EditableElement = editableElement.EditableElement.createFromFormItem(formItem);
             const plugin = Drupal.EditPlus.FieldPluginManager.getPlugin(EditableElement);
-            // @todo review this line as it changed from getData to getInputValue
             plugin.originalData.set(EditableElement.info.elementId, plugin.getInputValue(formItem));
+
           }
         })
         .catch(err => {
diff --git a/js/edit_plus/fields/media.js b/js/edit_plus/fields/media.js
index a98b370..01b5ec0 100644
--- a/js/edit_plus/fields/media.js
+++ b/js/edit_plus/fields/media.js
@@ -15,7 +15,7 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
       this.clonedElement = null;
     }
     supportedWidgets = [
-      'media_library',
+      'media_library_widget',
     ];
     focusElement(EditableElement) {
       this.originalValue = EditableElement.getFormItemWrapper().querySelector('.edit-plus-field-value img').src;
diff --git a/modules/edit_plus_lb/src/EditPlusLbTempstoreRepository.php b/modules/edit_plus_lb/src/EditPlusLbTempstoreRepository.php
index f22e9d3..9409c3a 100644
--- a/modules/edit_plus_lb/src/EditPlusLbTempstoreRepository.php
+++ b/modules/edit_plus_lb/src/EditPlusLbTempstoreRepository.php
@@ -12,6 +12,7 @@ use Drupal\layout_builder\SectionStorageInterface;
 use Drupal\layout_builder\LayoutEntityHelperTrait;
 use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
 use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay;
+use Drupal\layout_builder\Plugin\SectionStorage\DefaultsSectionStorage;
 use Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface;
 use Drupal\edit_plus\EditPlusTempstoreRepository as EditPlusTempstoreRepositoryBase;
 
@@ -20,7 +21,9 @@ use Drupal\edit_plus\EditPlusTempstoreRepository as EditPlusTempstoreRepositoryB
  */
 class EditPlusLbTempstoreRepository extends EditPlusTempstoreRepositoryBase {
 
-  use LayoutEntityHelperTrait;
+  use LayoutEntityHelperTrait {
+    getSectionStorageForEntity as lbGetSectionStorageForEntity;
+  }
 
   public function __construct(
     protected SharedTempStoreFactory $tempStoreFactory,
@@ -93,14 +96,24 @@ class EditPlusLbTempstoreRepository extends EditPlusTempstoreRepositoryBase {
    *   The section storage for the entity.
    */
   private function getSectionStorageForEntity(EntityInterface $entity): ?SectionStorageInterface {
-    $view_mode = 'full';
-    $contexts['entity'] = EntityContext::fromEntity($entity);
-    $view_mode = LayoutBuilderEntityViewDisplay::collectRenderDisplay($entity, $view_mode)->getMode();
-    $contexts['view_mode'] = new Context(new ContextDefinition('string'), $view_mode);
-
-    $section_storage = $this->sectionStorageManager->load('overrides', $contexts);
-    if (empty($section_storage)) {
-      return NULL;
+    $section_storage = $this->lbGetSectionStorageForEntity($entity);
+    if ($section_storage instanceof DefaultsSectionStorage) {
+      $view_mode = 'full';
+      $contexts['entity'] = EntityContext::fromEntity($entity);
+      $view_mode = LayoutBuilderEntityViewDisplay::collectRenderDisplay($entity, $view_mode)->getMode();
+      $contexts['view_mode'] = new Context(new ContextDefinition('string'), $view_mode);
+
+      $override_section_storage = $this->sectionStorageManager->load('overrides', $contexts);
+      if (empty($override_section_storage)) {
+        return NULL;
+      }
+      $sections = $section_storage->getSections();
+      if (!empty($sections)) {
+        foreach ($sections as $section) {
+          $override_section_storage->appendSection($section);
+        }
+      }
+      $section_storage = $override_section_storage ;
     }
     return $section_storage;
   }
diff --git a/package-lock.json b/package-lock.json
index 7a21f97..a9458b2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,107 +5,676 @@
     "packages": {
         "": {
             "devDependencies": {
-                "@ckeditor/ckeditor5-editor-inline": "40.2.0"
+                "@ckeditor/ckeditor5-editor-inline": "~42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-adapter-ckfinder": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-adapter-ckfinder/-/ckeditor5-adapter-ckfinder-42.0.2.tgz",
+            "integrity": "sha512-nX624WYyyJh6BGGy7jNOlEyf+Kv95VWHKlqn39HLTLKlONBp3zBhAtN9rd0gqU5EM6FgPQ+RjOtQinuto0B6oQ==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-upload": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-alignment": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-alignment/-/ckeditor5-alignment-42.0.2.tgz",
+            "integrity": "sha512-g6I0f5Ko7tckHrKYyZhNQL3dGHTcMbjypIfEkk3SAv68X4bDKLImVUJ1L6y0aZnGNoI40cMr0byEyln5rOq67Q==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-autoformat": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autoformat/-/ckeditor5-autoformat-42.0.2.tgz",
+            "integrity": "sha512-tnMdNc8VJ4y4wqbkSAbBGRiUukByOo1nBqyvzYS+SZ2Wzo67OmzKybvqz60PFYIbPAQJa0/uFkvgd55c+VTaqg==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-autosave": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autosave/-/ckeditor5-autosave-42.0.2.tgz",
+            "integrity": "sha512-QIsftrJ6LjJrmUTDfJYpBKy9DJ79ltt2pMHtb8DhoyugGZUup40pFvMrt/4/UuQRm64jS/IjhwWXkSMg4PejJw==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-basic-styles": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-basic-styles/-/ckeditor5-basic-styles-42.0.2.tgz",
+            "integrity": "sha512-LT0Kk1K30z/YhI48QBDa69tjU1G2ljSKi5pU5pfiSBLhMl1ShLmXIAy6cEHnijHS0mte8FGwhiGXmNB/jAZ7Iw==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-block-quote": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-block-quote/-/ckeditor5-block-quote-42.0.2.tgz",
+            "integrity": "sha512-xfX+tdAhn7WPHNNZR5Wkjl+OnmbNlEOVVZCL2iAjfswf4r3CglLnJOa529FO+4MyNcwkP+joQ3iVBclZNbETLw==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-enter": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-ckbox": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ckbox/-/ckeditor5-ckbox-42.0.2.tgz",
+            "integrity": "sha512-RvCUphlhrTuGBy78kEOFJvdvmP3o7ajibubOOpVfUMz1V8BbTmmx1+XaveCDxznkwiCLUwqZplWZnpPoEABj2w==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-upload": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "blurhash": "2.0.5",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-ckfinder": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ckfinder/-/ckeditor5-ckfinder-42.0.2.tgz",
+            "integrity": "sha512-3lkMF+9Z3R1OUfwZJdORlRDgPSyR9Be57zgizpevpKTenxrZ+UU33ib/kvK8LXVDOzz3qp7UyCucLfY1KNXCzA==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
             }
         },
         "node_modules/@ckeditor/ckeditor5-clipboard": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-40.2.0.tgz",
-            "integrity": "sha512-8/xPH9/i86ukcEiHdmTgNuPVJeYTrivbx5ZYqycPO4Eem7VM99gIbOe7pIYpuV+klr9ymVxIHbGyTJDJ3oUO8A==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-42.0.2.tgz",
+            "integrity": "sha512-x76SjAhaguwVQtJSgz62q96RsJsw0eSM7ZnuUqLjMMzO+hq2hAj7ZIJNPcA46ZyDR6LDQzH760IumSz0xlHn9w==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-engine": "40.2.0",
-                "@ckeditor/ckeditor5-ui": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0",
-                "@ckeditor/ckeditor5-widget": "40.2.0",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-cloud-services": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-cloud-services/-/ckeditor5-cloud-services-42.0.2.tgz",
+            "integrity": "sha512-oNdtgD/suEh5nAndXsjik8HgRDk095EGxkmrMO+Z3gbOit28fvTDL6bbUOQvenoNNWa7RXLZMbfyiTMuNH+X8Q==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-code-block": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-code-block/-/ckeditor5-code-block-42.0.2.tgz",
+            "integrity": "sha512-NFGn+350VS6/UNhHm9CurOLm3ZiXFUCO/SgKRILPKZ82Wh2GQqocs5O3yvvo1WQ9jA2DEwjfN0TgOpwgVOZQPQ==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-enter": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
                 "lodash-es": "4.17.21"
             }
         },
         "node_modules/@ckeditor/ckeditor5-core": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-40.2.0.tgz",
-            "integrity": "sha512-0fqIaN+ZhkXXA3mpBN+alycBzPMc8ruO8VrP0OnvCjowqZVS2HXC2AaXNBdxc75xGI3ScXIor7FsgFHxVJIYYQ==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-42.0.2.tgz",
+            "integrity": "sha512-LkNx1Qpk/gwh0wYkl4FdZfi1N2G5Gmp026sVp301boyE9sSVeR3YxcSdKXfsr2HII+7EdJHxMswTvnd/L+IdSg==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-watchdog": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-easy-image": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-easy-image/-/ckeditor5-easy-image-42.0.2.tgz",
+            "integrity": "sha512-JYVpX6lRVRve8roROx5y6nsixLXLuVwIokBLoo+usS313xeeZvjoLrxGTeRuyyVbK3BFPE+zqyXsgqGs1Q0stg==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-upload": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-editor-balloon": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-balloon/-/ckeditor5-editor-balloon-42.0.2.tgz",
+            "integrity": "sha512-NXTVQ3aBW8OirKgv8PJvjSDDbl39JGlnS/W+/LRwUlOgHVVWHVSMMqY52AhP90TzP6xfbFYBYX8n13EB6o/4Bw==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-engine": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-editor-classic": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-classic/-/ckeditor5-editor-classic-42.0.2.tgz",
+            "integrity": "sha512-K9+154AP/OpxDn6702772QCiT830lAQXsiUty1Z35MM3hVS5quwkuxS6V0NjKxx0AcqUmmgdXoFxx6v4mj3R7g==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-editor-decoupled": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-decoupled/-/ckeditor5-editor-decoupled-42.0.2.tgz",
+            "integrity": "sha512-ANhlpcZXV+nZl/f9o+wS5vqc+Va5K4LnYA0F/pJNTNlighVCa1nGQX11tRGm48vItpNlgQxty+p86NHa+7YrLw==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
                 "lodash-es": "4.17.21"
             }
         },
         "node_modules/@ckeditor/ckeditor5-editor-inline": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-inline/-/ckeditor5-editor-inline-40.2.0.tgz",
-            "integrity": "sha512-Ox9lQiCSv0acyKaQLCcoebBjAMRE6L6iCBN8XVeQ3u91KZV6/LOhP+CJ314c8AuH+UHPeJt9MHP6eGU0trKHGQ==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-inline/-/ckeditor5-editor-inline-42.0.2.tgz",
+            "integrity": "sha512-gWngpGE/6JDCyKpKTX7iIgFaxrDPzocZt56p1JmBJCNpVQb4sGoZs94uUg7rxlVo8t3PDH+foL49gSdBKYS9uw==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-editor-multi-root": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-multi-root/-/ckeditor5-editor-multi-root-42.0.2.tgz",
+            "integrity": "sha512-1Cv4WGB75KoWZWewCOnHP4s4HGFXKt3BajvDkN8LXS6CtaIPDkH18okY/ivH/Idhu1pT9k2bjzCfR7W4EhtRJg==",
             "dev": true,
             "dependencies": {
-                "ckeditor5": "40.2.0",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
                 "lodash-es": "4.17.21"
             }
         },
         "node_modules/@ckeditor/ckeditor5-engine": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-40.2.0.tgz",
-            "integrity": "sha512-sgboUX8Ps+LcEgywyT3BeK1nzLHjNVIiZU1qvRxR3ixzIw4w2xRNXCGfESWLW5Y5rv9+ypUCrX61oLnZU64PQQ==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-42.0.2.tgz",
+            "integrity": "sha512-mI4+X6Z0ihnyAKzka5RjoUgZoaRDckMniN8LLYNum3ewz+KWIVjtHn6NBrqEqw24BpwYfSVEPL/NdgA6xl93Jw==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-utils": "40.2.0",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
                 "lodash-es": "4.17.21"
             }
         },
         "node_modules/@ckeditor/ckeditor5-enter": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-40.2.0.tgz",
-            "integrity": "sha512-GjTRaKNX8QEDJ3YYKG3GfPZfGHrcigGBxbo+1WDT7NaOsR2DA/CIZfHlAPfgJDAMV17bhWsT3gy3+oQZsExtnQ==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-42.0.2.tgz",
+            "integrity": "sha512-pzVXQPdBgskiqVpCG/yxliuEXPECCI3GJ/OF5wXs2GQ04IcqBz5FsazUtSLS5nnA4e3YpcdzzEC0Kn1ASdl7QQ==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-essentials": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-essentials/-/ckeditor5-essentials-42.0.2.tgz",
+            "integrity": "sha512-4qhW/7zm69KHnotKEs05YB6YTD6WB6QWJ6U44V6dFGJUUUmYN1fOt9ri6lU8snUVhJrU0C9IuGpVkb8Aby79GQ==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-engine": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0"
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-enter": "42.0.2",
+                "@ckeditor/ckeditor5-select-all": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-undo": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-find-and-replace": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-find-and-replace/-/ckeditor5-find-and-replace-42.0.2.tgz",
+            "integrity": "sha512-9Fc5nKUhDtivHxGoY5nEvwjqUyvMwcNs1Xo6nt9aXeG0gd4mrCdUQaQfRIlcycLmeVD1MgKfWh7sOv+EtuYFRA==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-font": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-font/-/ckeditor5-font-42.0.2.tgz",
+            "integrity": "sha512-Soj1auf82Zz6y56qKf6nV6RSjNPENZm9vpkJ9jhyQ4pMh6YvQ7EkzbOwPCoskXm+ab8EAuH+bjS0n5lewN5i7Q==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-heading": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-heading/-/ckeditor5-heading-42.0.2.tgz",
+            "integrity": "sha512-1lwxsxzJRikSerwhH1By9FlAO2EQhcrt3xnpxBFME3pS2Y6tbkHj81W5Lu2cf+0ew5Bzcp5uqTvaArRtVssY1A==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-paragraph": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-highlight": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-highlight/-/ckeditor5-highlight-42.0.2.tgz",
+            "integrity": "sha512-I/qVqC1YS6Hfg1dZjP665NU2fIx5Dk4Rjq2ku7yxQrsmG+rle2xrEzXF1BsaBeK6ko+fX7JaP86dTvywnnOeaw==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-horizontal-line": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-horizontal-line/-/ckeditor5-horizontal-line-42.0.2.tgz",
+            "integrity": "sha512-zXnK2k5F5lhbLVwHzyURPMRGc8pc1YPz8fYXmz1pf/JG/EgXGGuUlczkpzegBUb9MctFgZbs09xIkTkVBQZmNw==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-html-embed": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-html-embed/-/ckeditor5-html-embed-42.0.2.tgz",
+            "integrity": "sha512-aqCV9vQJd6KiYsTEW6UlWtyMTZgXI2oHK7/1p8WUagabHU1ZFT+jkExC8QG9n0M76Sq9TIynqBlfl4OOijT6NQ==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-html-support": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-html-support/-/ckeditor5-html-support-42.0.2.tgz",
+            "integrity": "sha512-z+Tg/jOf9+wzCo/NywkuHPGfOnKHfSr0hvkGjrq8b2OU9B1nJI34VTjJWSFH5NfLpn3tZo2dy3EcaoN9B7rSHA==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-enter": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-image": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-image/-/ckeditor5-image-42.0.2.tgz",
+            "integrity": "sha512-RH1r10rsnEFSBNBXe3d02J6JDvoLKxwz/KCvC/EoOR4UEKDe0FNodt3+VZrb0JNqkBUIxqdtvEobXb6YmGQaDQ==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-undo": "42.0.2",
+                "@ckeditor/ckeditor5-upload": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-indent": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-indent/-/ckeditor5-indent-42.0.2.tgz",
+            "integrity": "sha512-qXVXqvflW8kKa7odjiSTrQtj75C5opmnGUyrM+37f7CC8OmrcjXJ5GgrFnKwHyny9YHtvQyyN+GCuzuir6a9eA==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-language": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-language/-/ckeditor5-language-42.0.2.tgz",
+            "integrity": "sha512-s0pMdNxuE+kBCFiop5Lgv/UsYAYLKCENesMXVIRrxI73GRjwJXIq5f/5a7xwvfmH3/TQT5GMrfNmf5EeYo5NHA==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-link": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-link/-/ckeditor5-link-42.0.2.tgz",
+            "integrity": "sha512-KySX11v1RyimZyc4u3AF6a/bEvA3gQg/krRsrzBbMIadtC1WN/C7w7XzjmYvx8Ui0SsH/ChBu16SxmRKO4HuTA==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-list": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-list/-/ckeditor5-list-42.0.2.tgz",
+            "integrity": "sha512-NTNDb01QDyjDZis8nyOsvgSNwy6YniulGDZdyeulhmFy6zyHG0GFeYA0kAyW6/bnniWyW9cpfUrAK9KTLuql4A==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-enter": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-markdown-gfm": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-markdown-gfm/-/ckeditor5-markdown-gfm-42.0.2.tgz",
+            "integrity": "sha512-mh81YHQqVF0ZVSgd7hbO3EzuM78zIhwwZiiVsJ68e4aCfpYjc3Ni1NpyORj+tian743PmFr7WAUqIePdNPmQEg==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "marked": "4.0.12",
+                "turndown": "7.2.0",
+                "turndown-plugin-gfm": "1.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-media-embed": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-media-embed/-/ckeditor5-media-embed-42.0.2.tgz",
+            "integrity": "sha512-iXGcfgOm0IWa600ln5YeSssg7Sew6Lf1z9ziTxsQsmforPIqXgZQEvdLoo0tABddSRQZI+yQZnRnwrus9sZXIA==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-undo": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-mention": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-mention/-/ckeditor5-mention-42.0.2.tgz",
+            "integrity": "sha512-81MYULfB7bHDb5Y7saIZMkNVG1BJV/ir5BwIDuuXwGXLNVX++uMTK4ryAItYToiSFN8/NBms7JFXPrRhL/zbOw==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-minimap": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-minimap/-/ckeditor5-minimap-42.0.2.tgz",
+            "integrity": "sha512-dOBT6bS/7tREFmpRCD4XwOEmoW4p7ZV1Pp3tA/KYQ++2BAgI/O/Yeww7nlhsKhal4r74v459hgihI/SnlfqBQA==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-page-break": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-page-break/-/ckeditor5-page-break-42.0.2.tgz",
+            "integrity": "sha512-h6Wb0fWsl4a0MyU8W3F4Yku/1CWnR6tQrcMapn0sHB9W/HAvHLQIJGdsYh+a1W6QzMIjpVAqjT4mxQ1rU86RkQ==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "ckeditor5": "42.0.2"
             }
         },
         "node_modules/@ckeditor/ckeditor5-paragraph": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-40.2.0.tgz",
-            "integrity": "sha512-NotxWP1cKvbJSY1UwdTe/Oy1NnAj9Etsi4Z7XA908EvCsNSnFtzdMhYzLhFZJ18avrQFDa7PpSKSyN3M64CbSA==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-42.0.2.tgz",
+            "integrity": "sha512-feI7Rw76uPbPmoFeVEPpKdPTOjdlccpWabhfrimgT08rECLa7ErFw2oRZVmnx5+kjX+NAUeD9kaUZUUkNNP0wg==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-paste-from-office": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paste-from-office/-/ckeditor5-paste-from-office-42.0.2.tgz",
+            "integrity": "sha512-9K54E44rEjvLqWKRRHeifOlb1bICKzzX8gOv/i90sFQfMeQphA6qEn3WJZNQY4NY9Uwhu3kF/gh3/dqlcBhsvw==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-remove-format": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-remove-format/-/ckeditor5-remove-format-42.0.2.tgz",
+            "integrity": "sha512-YIyKibU44Jt6P9qu3WGPjUUh/pb5dvexeE1XG6f5JNtVlZCy3sUI+BDytzqWI68/coOHBKYkKSDOEQdzw83PdA==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-ui": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0"
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-restricted-editing": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-restricted-editing/-/ckeditor5-restricted-editing-42.0.2.tgz",
+            "integrity": "sha512-tfnEE6ieR2UhjZ9zoDNfXIMAMy2FWoajASKffdtpTMBjkVKzM+isg8j0hEkWgiQqCsJYVWt0314nPZrm5EUIfA==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
             }
         },
         "node_modules/@ckeditor/ckeditor5-select-all": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-40.2.0.tgz",
-            "integrity": "sha512-yaYCqhdMcoEH3BsilhweNdbOfuO/cexQ1r1/mYoBoW4CypIuAeq8J/3qLpvFaThmCRPzJBn1J7v2Yjs/0UnamA==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-42.0.2.tgz",
+            "integrity": "sha512-eqLhxmsxDQ8s+Op4f0OoXbN9vwz0hekE1HxsClXIsqwhjsO2o/HYcyhIzR9lPgmi4bVf8uy8T9oyWQNRLv4S9w==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-show-blocks": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-show-blocks/-/ckeditor5-show-blocks-42.0.2.tgz",
+            "integrity": "sha512-CFYJN3gyiWwJ1mDonzIktRL/A+WONZuyCptELqlU51RRCwbG7eSMtu2Eyd+Q463zYbOKZcdr5uNvlWuRpSsalw==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-source-editing": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-source-editing/-/ckeditor5-source-editing-42.0.2.tgz",
+            "integrity": "sha512-lo/ZmBeAoWu9j0qfuUVIpc2QzZmcrYZ2enloz2mL22DCn3eP8IstE7gSmZlQ/DQxcPC5Sf2uC0l9IurBAP9+pg==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-theme-lark": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-special-characters": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-special-characters/-/ckeditor5-special-characters-42.0.2.tgz",
+            "integrity": "sha512-B2E9thXW0Ej1istiResH6987g+REnX18aoxW4uXG+PHDrYWjsV4fClEnjWdkO/O0A3yOoNc4LYAbGSo7z0g/1g==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-style": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-style/-/ckeditor5-style-42.0.2.tgz",
+            "integrity": "sha512-vq1GSeOtZm00W4FC6MgqukJbdDE394Sh7ID6634gKmdknbxOBvNcF0XUdAu+kWtJzTjYVrC4+oPYpS5C+odidQ==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-table": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-table/-/ckeditor5-table-42.0.2.tgz",
+            "integrity": "sha512-fFMXbQCa7UR4aAmwVkKzDcRmKCd2YwE1iNLeGWJz7tz1c+hGeadej0aHgUxBw+hHu6DhS9AyvtwmNweQpc3PnQ==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "node_modules/@ckeditor/ckeditor5-theme-lark": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-theme-lark/-/ckeditor5-theme-lark-42.0.2.tgz",
+            "integrity": "sha512-t+/JVtK+lWzfLywsZX7eE8tfyBSnsaTsxeo84ZbSU9M1Vts5FN/5JExiY89VjsT8m84VAufbG+fDGjQpiYzsyg==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-ui": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0"
+                "@ckeditor/ckeditor5-ui": "42.0.2"
             }
         },
         "node_modules/@ckeditor/ckeditor5-typing": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-40.2.0.tgz",
-            "integrity": "sha512-2E7LkmC4RHdenMUwow0EZDKxlbX00c5UHysUVT51EBGrXiJcN++0cqxQaeJzQ262oTDpk94qE5IZdGXt3ntzrw==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-42.0.2.tgz",
+            "integrity": "sha512-xwGazKjCJOQViGnk/Q0yVg98mc0aDJHvx6FsCFRF6e7B8WiMq8rPQjfO63TYOnUSOIkQJerbAv+hrsBS8XdxaQ==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-engine": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
                 "lodash-es": "4.17.21"
             }
         },
         "node_modules/@ckeditor/ckeditor5-ui": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-40.2.0.tgz",
-            "integrity": "sha512-K8oC9zrJokZD5Nl4uQjJMo8Couds0eHmfNI/go6iU4A4OAdDzph+W50QnyMed4etKnMdhvUSbnuZnPtQjnsvFA==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-42.0.2.tgz",
+            "integrity": "sha512-Lrej61+xTTqIJSlA9FfqwpEClVoRabM3na8MDiWjAzneQkPgFtw1WTgUKvxNaI+eMXCmT/HVNj/RCg9vqt0pug==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
                 "color-convert": "2.0.1",
                 "color-parse": "1.4.2",
                 "lodash-es": "4.17.21",
@@ -113,79 +682,147 @@
             }
         },
         "node_modules/@ckeditor/ckeditor5-undo": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-40.2.0.tgz",
-            "integrity": "sha512-k2VZS5x4SJtYk3zhdwHYg+D00DgD0iWR0H4qQgcWmQMFRipYvXJRixP3hSLZGJciQanPFeYcjZgxNQ+rU1s8ug==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-42.0.2.tgz",
+            "integrity": "sha512-OpfdYnADY2MM8nWN5M13BEDDnwL15YHUYUpgMnydgJObZzSnePqgWQSFaBAY5j24eze0a8gyGgnOE5jV6VBm1Q==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-engine": "40.2.0",
-                "@ckeditor/ckeditor5-ui": "40.2.0"
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2"
             }
         },
         "node_modules/@ckeditor/ckeditor5-upload": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-40.2.0.tgz",
-            "integrity": "sha512-AdJSKvWEQbSSyA/DfxbCHRhFN6S4ew4kuYETO57e6AS3aOuYGLBRdu9Mub7IAQcOyy1LL6ktr9u5WEOoWS2h0w==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-42.0.2.tgz",
+            "integrity": "sha512-QD6PR1ZurGQv0gULG4hNiaFMO306qM9Gin2BbICkZuJ+IFKd7nQ+mp7ZCbgPgRYtSkeUyHjSzNR4+wIA2nPVEg==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-ui": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0"
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2"
             }
         },
         "node_modules/@ckeditor/ckeditor5-utils": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-40.2.0.tgz",
-            "integrity": "sha512-f+kTJBwwk7Y/LXm8pEPxBTXVlJwQrH7Levzye9zxEDB0Jtj7+brGr87o666fPmL/ATQc5M+VPhbvnk2sOv7WKg==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-42.0.2.tgz",
+            "integrity": "sha512-z4lNVoVf4cyK6cugMABNgMtYDiIK+0eQwYFtr45DhPK283RWEqrU0xwbwoqhIqeXRQ6B+9+0nC7ZIFPEdQ+iDA==",
             "dev": true,
             "dependencies": {
                 "lodash-es": "4.17.21"
             }
         },
         "node_modules/@ckeditor/ckeditor5-watchdog": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-40.2.0.tgz",
-            "integrity": "sha512-ets7o2dUR7l23G9o/RAbu+gJzUkc2Ul269E3TEhZnbQXFjshvEGK2kzuay7I+/waL3ADuYe4zuoBqsqdPoAhfg==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-42.0.2.tgz",
+            "integrity": "sha512-0z00yqbBt/JALAD8C62LNySitQ+wBw1My43Qe2xs5VAP5tUZcziFFCc4BhMy+w6ZWUmZj2hkjSLlmx7b/vid+A==",
             "dev": true,
             "dependencies": {
                 "lodash-es": "4.17.21"
             }
         },
         "node_modules/@ckeditor/ckeditor5-widget": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-40.2.0.tgz",
-            "integrity": "sha512-okeUSwbnu6TUKvwBOl0YdED6Me0/vvs1ybfKZPNEJNwGl989iG0LQO4oYUye8BTCZvzCZ2cBTb1Cvnwr8KRcbg==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-42.0.2.tgz",
+            "integrity": "sha512-ZRI8H+Ir7YpByUO4/kKMNJJE5WUDoICl1BitSR9QKmkG7X2fBRdDG8setm4HsUU1kkPe0aYy6HK2ajZ2g5ZkaA==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-engine": "40.2.0",
-                "@ckeditor/ckeditor5-enter": "40.2.0",
-                "@ckeditor/ckeditor5-typing": "40.2.0",
-                "@ckeditor/ckeditor5-ui": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-enter": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
                 "lodash-es": "4.17.21"
             }
         },
+        "node_modules/@ckeditor/ckeditor5-word-count": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-word-count/-/ckeditor5-word-count-42.0.2.tgz",
+            "integrity": "sha512-jtlyA6TXnnRpaTgvYG219z5p+MRZWUBz3r5oHa79lFcMDREZH6gKztiE+hYSmiL2OSAtHi0kYWUAF/oJfpHt3g==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "node_modules/@mixmark-io/domino": {
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz",
+            "integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==",
+            "dev": true
+        },
+        "node_modules/blurhash": {
+            "version": "2.0.5",
+            "resolved": "https://registry.npmjs.org/blurhash/-/blurhash-2.0.5.tgz",
+            "integrity": "sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==",
+            "dev": true
+        },
         "node_modules/ckeditor5": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-40.2.0.tgz",
-            "integrity": "sha512-JaFuY/6DX1wbA6yRB2xQVMr+9W1C3HvSX4AT10ccoKBKe9OctIatekDt2ztV+cMaVHLF1wocskS/Ql9XFRy2Eg==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-clipboard": "40.2.0",
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-engine": "40.2.0",
-                "@ckeditor/ckeditor5-enter": "40.2.0",
-                "@ckeditor/ckeditor5-paragraph": "40.2.0",
-                "@ckeditor/ckeditor5-select-all": "40.2.0",
-                "@ckeditor/ckeditor5-typing": "40.2.0",
-                "@ckeditor/ckeditor5-ui": "40.2.0",
-                "@ckeditor/ckeditor5-undo": "40.2.0",
-                "@ckeditor/ckeditor5-upload": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0",
-                "@ckeditor/ckeditor5-watchdog": "40.2.0",
-                "@ckeditor/ckeditor5-widget": "40.2.0"
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-42.0.2.tgz",
+            "integrity": "sha512-SHyyJ6y/+2Mas3SMlVchsq1i9LYqF7J7EMwEUKAt+sIXBW9pbBnLVncXpIpGTQ/M8fS20NVk7dfJ2P4TyEZGew==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-adapter-ckfinder": "42.0.2",
+                "@ckeditor/ckeditor5-alignment": "42.0.2",
+                "@ckeditor/ckeditor5-autoformat": "42.0.2",
+                "@ckeditor/ckeditor5-autosave": "42.0.2",
+                "@ckeditor/ckeditor5-basic-styles": "42.0.2",
+                "@ckeditor/ckeditor5-block-quote": "42.0.2",
+                "@ckeditor/ckeditor5-ckbox": "42.0.2",
+                "@ckeditor/ckeditor5-ckfinder": "42.0.2",
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-cloud-services": "42.0.2",
+                "@ckeditor/ckeditor5-code-block": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-easy-image": "42.0.2",
+                "@ckeditor/ckeditor5-editor-balloon": "42.0.2",
+                "@ckeditor/ckeditor5-editor-classic": "42.0.2",
+                "@ckeditor/ckeditor5-editor-decoupled": "42.0.2",
+                "@ckeditor/ckeditor5-editor-inline": "42.0.2",
+                "@ckeditor/ckeditor5-editor-multi-root": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-enter": "42.0.2",
+                "@ckeditor/ckeditor5-essentials": "42.0.2",
+                "@ckeditor/ckeditor5-find-and-replace": "42.0.2",
+                "@ckeditor/ckeditor5-font": "42.0.2",
+                "@ckeditor/ckeditor5-heading": "42.0.2",
+                "@ckeditor/ckeditor5-highlight": "42.0.2",
+                "@ckeditor/ckeditor5-horizontal-line": "42.0.2",
+                "@ckeditor/ckeditor5-html-embed": "42.0.2",
+                "@ckeditor/ckeditor5-html-support": "42.0.2",
+                "@ckeditor/ckeditor5-image": "42.0.2",
+                "@ckeditor/ckeditor5-indent": "42.0.2",
+                "@ckeditor/ckeditor5-language": "42.0.2",
+                "@ckeditor/ckeditor5-link": "42.0.2",
+                "@ckeditor/ckeditor5-list": "42.0.2",
+                "@ckeditor/ckeditor5-markdown-gfm": "42.0.2",
+                "@ckeditor/ckeditor5-media-embed": "42.0.2",
+                "@ckeditor/ckeditor5-mention": "42.0.2",
+                "@ckeditor/ckeditor5-minimap": "42.0.2",
+                "@ckeditor/ckeditor5-page-break": "42.0.2",
+                "@ckeditor/ckeditor5-paragraph": "42.0.2",
+                "@ckeditor/ckeditor5-paste-from-office": "42.0.2",
+                "@ckeditor/ckeditor5-remove-format": "42.0.2",
+                "@ckeditor/ckeditor5-restricted-editing": "42.0.2",
+                "@ckeditor/ckeditor5-select-all": "42.0.2",
+                "@ckeditor/ckeditor5-show-blocks": "42.0.2",
+                "@ckeditor/ckeditor5-source-editing": "42.0.2",
+                "@ckeditor/ckeditor5-special-characters": "42.0.2",
+                "@ckeditor/ckeditor5-style": "42.0.2",
+                "@ckeditor/ckeditor5-table": "42.0.2",
+                "@ckeditor/ckeditor5-theme-lark": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-undo": "42.0.2",
+                "@ckeditor/ckeditor5-upload": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-watchdog": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "@ckeditor/ckeditor5-word-count": "42.0.2"
             }
         },
         "node_modules/color-convert": {
@@ -221,6 +858,33 @@
             "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
             "dev": true
         },
+        "node_modules/marked": {
+            "version": "4.0.12",
+            "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz",
+            "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==",
+            "dev": true,
+            "bin": {
+                "marked": "bin/marked.js"
+            },
+            "engines": {
+                "node": ">= 12"
+            }
+        },
+        "node_modules/turndown": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.0.tgz",
+            "integrity": "sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==",
+            "dev": true,
+            "dependencies": {
+                "@mixmark-io/domino": "^2.2.0"
+            }
+        },
+        "node_modules/turndown-plugin-gfm": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.2.tgz",
+            "integrity": "sha512-vwz9tfvF7XN/jE0dGoBei3FXWuvll78ohzCZQuOb+ZjWrs3a0XhQVomJEb2Qh4VHTPNRO4GPZh0V7VRbiWwkRg==",
+            "dev": true
+        },
         "node_modules/vanilla-colorful": {
             "version": "0.7.2",
             "resolved": "https://registry.npmjs.org/vanilla-colorful/-/vanilla-colorful-0.7.2.tgz",
@@ -229,104 +893,673 @@
         }
     },
     "dependencies": {
+        "@ckeditor/ckeditor5-adapter-ckfinder": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-adapter-ckfinder/-/ckeditor5-adapter-ckfinder-42.0.2.tgz",
+            "integrity": "sha512-nX624WYyyJh6BGGy7jNOlEyf+Kv95VWHKlqn39HLTLKlONBp3zBhAtN9rd0gqU5EM6FgPQ+RjOtQinuto0B6oQ==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-upload": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-alignment": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-alignment/-/ckeditor5-alignment-42.0.2.tgz",
+            "integrity": "sha512-g6I0f5Ko7tckHrKYyZhNQL3dGHTcMbjypIfEkk3SAv68X4bDKLImVUJ1L6y0aZnGNoI40cMr0byEyln5rOq67Q==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-autoformat": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autoformat/-/ckeditor5-autoformat-42.0.2.tgz",
+            "integrity": "sha512-tnMdNc8VJ4y4wqbkSAbBGRiUukByOo1nBqyvzYS+SZ2Wzo67OmzKybvqz60PFYIbPAQJa0/uFkvgd55c+VTaqg==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-autosave": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autosave/-/ckeditor5-autosave-42.0.2.tgz",
+            "integrity": "sha512-QIsftrJ6LjJrmUTDfJYpBKy9DJ79ltt2pMHtb8DhoyugGZUup40pFvMrt/4/UuQRm64jS/IjhwWXkSMg4PejJw==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "@ckeditor/ckeditor5-basic-styles": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-basic-styles/-/ckeditor5-basic-styles-42.0.2.tgz",
+            "integrity": "sha512-LT0Kk1K30z/YhI48QBDa69tjU1G2ljSKi5pU5pfiSBLhMl1ShLmXIAy6cEHnijHS0mte8FGwhiGXmNB/jAZ7Iw==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-block-quote": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-block-quote/-/ckeditor5-block-quote-42.0.2.tgz",
+            "integrity": "sha512-xfX+tdAhn7WPHNNZR5Wkjl+OnmbNlEOVVZCL2iAjfswf4r3CglLnJOa529FO+4MyNcwkP+joQ3iVBclZNbETLw==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-enter": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-ckbox": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ckbox/-/ckeditor5-ckbox-42.0.2.tgz",
+            "integrity": "sha512-RvCUphlhrTuGBy78kEOFJvdvmP3o7ajibubOOpVfUMz1V8BbTmmx1+XaveCDxznkwiCLUwqZplWZnpPoEABj2w==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-upload": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "blurhash": "2.0.5",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "@ckeditor/ckeditor5-ckfinder": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ckfinder/-/ckeditor5-ckfinder-42.0.2.tgz",
+            "integrity": "sha512-3lkMF+9Z3R1OUfwZJdORlRDgPSyR9Be57zgizpevpKTenxrZ+UU33ib/kvK8LXVDOzz3qp7UyCucLfY1KNXCzA==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
         "@ckeditor/ckeditor5-clipboard": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-40.2.0.tgz",
-            "integrity": "sha512-8/xPH9/i86ukcEiHdmTgNuPVJeYTrivbx5ZYqycPO4Eem7VM99gIbOe7pIYpuV+klr9ymVxIHbGyTJDJ3oUO8A==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-42.0.2.tgz",
+            "integrity": "sha512-x76SjAhaguwVQtJSgz62q96RsJsw0eSM7ZnuUqLjMMzO+hq2hAj7ZIJNPcA46ZyDR6LDQzH760IumSz0xlHn9w==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-engine": "40.2.0",
-                "@ckeditor/ckeditor5-ui": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0",
-                "@ckeditor/ckeditor5-widget": "40.2.0",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "@ckeditor/ckeditor5-cloud-services": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-cloud-services/-/ckeditor5-cloud-services-42.0.2.tgz",
+            "integrity": "sha512-oNdtgD/suEh5nAndXsjik8HgRDk095EGxkmrMO+Z3gbOit28fvTDL6bbUOQvenoNNWa7RXLZMbfyiTMuNH+X8Q==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-code-block": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-code-block/-/ckeditor5-code-block-42.0.2.tgz",
+            "integrity": "sha512-NFGn+350VS6/UNhHm9CurOLm3ZiXFUCO/SgKRILPKZ82Wh2GQqocs5O3yvvo1WQ9jA2DEwjfN0TgOpwgVOZQPQ==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-enter": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
                 "lodash-es": "4.17.21"
             }
         },
         "@ckeditor/ckeditor5-core": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-40.2.0.tgz",
-            "integrity": "sha512-0fqIaN+ZhkXXA3mpBN+alycBzPMc8ruO8VrP0OnvCjowqZVS2HXC2AaXNBdxc75xGI3ScXIor7FsgFHxVJIYYQ==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-42.0.2.tgz",
+            "integrity": "sha512-LkNx1Qpk/gwh0wYkl4FdZfi1N2G5Gmp026sVp301boyE9sSVeR3YxcSdKXfsr2HII+7EdJHxMswTvnd/L+IdSg==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-engine": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-watchdog": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "@ckeditor/ckeditor5-easy-image": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-easy-image/-/ckeditor5-easy-image-42.0.2.tgz",
+            "integrity": "sha512-JYVpX6lRVRve8roROx5y6nsixLXLuVwIokBLoo+usS313xeeZvjoLrxGTeRuyyVbK3BFPE+zqyXsgqGs1Q0stg==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-upload": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-editor-balloon": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-balloon/-/ckeditor5-editor-balloon-42.0.2.tgz",
+            "integrity": "sha512-NXTVQ3aBW8OirKgv8PJvjSDDbl39JGlnS/W+/LRwUlOgHVVWHVSMMqY52AhP90TzP6xfbFYBYX8n13EB6o/4Bw==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "@ckeditor/ckeditor5-editor-classic": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-classic/-/ckeditor5-editor-classic-42.0.2.tgz",
+            "integrity": "sha512-K9+154AP/OpxDn6702772QCiT830lAQXsiUty1Z35MM3hVS5quwkuxS6V0NjKxx0AcqUmmgdXoFxx6v4mj3R7g==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "@ckeditor/ckeditor5-editor-decoupled": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-decoupled/-/ckeditor5-editor-decoupled-42.0.2.tgz",
+            "integrity": "sha512-ANhlpcZXV+nZl/f9o+wS5vqc+Va5K4LnYA0F/pJNTNlighVCa1nGQX11tRGm48vItpNlgQxty+p86NHa+7YrLw==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
                 "lodash-es": "4.17.21"
             }
         },
         "@ckeditor/ckeditor5-editor-inline": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-inline/-/ckeditor5-editor-inline-40.2.0.tgz",
-            "integrity": "sha512-Ox9lQiCSv0acyKaQLCcoebBjAMRE6L6iCBN8XVeQ3u91KZV6/LOhP+CJ314c8AuH+UHPeJt9MHP6eGU0trKHGQ==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-inline/-/ckeditor5-editor-inline-42.0.2.tgz",
+            "integrity": "sha512-gWngpGE/6JDCyKpKTX7iIgFaxrDPzocZt56p1JmBJCNpVQb4sGoZs94uUg7rxlVo8t3PDH+foL49gSdBKYS9uw==",
             "dev": true,
             "requires": {
-                "ckeditor5": "40.2.0",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "@ckeditor/ckeditor5-editor-multi-root": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-multi-root/-/ckeditor5-editor-multi-root-42.0.2.tgz",
+            "integrity": "sha512-1Cv4WGB75KoWZWewCOnHP4s4HGFXKt3BajvDkN8LXS6CtaIPDkH18okY/ivH/Idhu1pT9k2bjzCfR7W4EhtRJg==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
                 "lodash-es": "4.17.21"
             }
         },
         "@ckeditor/ckeditor5-engine": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-40.2.0.tgz",
-            "integrity": "sha512-sgboUX8Ps+LcEgywyT3BeK1nzLHjNVIiZU1qvRxR3ixzIw4w2xRNXCGfESWLW5Y5rv9+ypUCrX61oLnZU64PQQ==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-42.0.2.tgz",
+            "integrity": "sha512-mI4+X6Z0ihnyAKzka5RjoUgZoaRDckMniN8LLYNum3ewz+KWIVjtHn6NBrqEqw24BpwYfSVEPL/NdgA6xl93Jw==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-utils": "40.2.0",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
                 "lodash-es": "4.17.21"
             }
         },
         "@ckeditor/ckeditor5-enter": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-40.2.0.tgz",
-            "integrity": "sha512-GjTRaKNX8QEDJ3YYKG3GfPZfGHrcigGBxbo+1WDT7NaOsR2DA/CIZfHlAPfgJDAMV17bhWsT3gy3+oQZsExtnQ==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-42.0.2.tgz",
+            "integrity": "sha512-pzVXQPdBgskiqVpCG/yxliuEXPECCI3GJ/OF5wXs2GQ04IcqBz5FsazUtSLS5nnA4e3YpcdzzEC0Kn1ASdl7QQ==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-essentials": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-essentials/-/ckeditor5-essentials-42.0.2.tgz",
+            "integrity": "sha512-4qhW/7zm69KHnotKEs05YB6YTD6WB6QWJ6U44V6dFGJUUUmYN1fOt9ri6lU8snUVhJrU0C9IuGpVkb8Aby79GQ==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-enter": "42.0.2",
+                "@ckeditor/ckeditor5-select-all": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-undo": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-find-and-replace": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-find-and-replace/-/ckeditor5-find-and-replace-42.0.2.tgz",
+            "integrity": "sha512-9Fc5nKUhDtivHxGoY5nEvwjqUyvMwcNs1Xo6nt9aXeG0gd4mrCdUQaQfRIlcycLmeVD1MgKfWh7sOv+EtuYFRA==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "@ckeditor/ckeditor5-font": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-font/-/ckeditor5-font-42.0.2.tgz",
+            "integrity": "sha512-Soj1auf82Zz6y56qKf6nV6RSjNPENZm9vpkJ9jhyQ4pMh6YvQ7EkzbOwPCoskXm+ab8EAuH+bjS0n5lewN5i7Q==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-heading": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-heading/-/ckeditor5-heading-42.0.2.tgz",
+            "integrity": "sha512-1lwxsxzJRikSerwhH1By9FlAO2EQhcrt3xnpxBFME3pS2Y6tbkHj81W5Lu2cf+0ew5Bzcp5uqTvaArRtVssY1A==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-paragraph": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-highlight": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-highlight/-/ckeditor5-highlight-42.0.2.tgz",
+            "integrity": "sha512-I/qVqC1YS6Hfg1dZjP665NU2fIx5Dk4Rjq2ku7yxQrsmG+rle2xrEzXF1BsaBeK6ko+fX7JaP86dTvywnnOeaw==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-horizontal-line": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-horizontal-line/-/ckeditor5-horizontal-line-42.0.2.tgz",
+            "integrity": "sha512-zXnK2k5F5lhbLVwHzyURPMRGc8pc1YPz8fYXmz1pf/JG/EgXGGuUlczkpzegBUb9MctFgZbs09xIkTkVBQZmNw==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-html-embed": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-html-embed/-/ckeditor5-html-embed-42.0.2.tgz",
+            "integrity": "sha512-aqCV9vQJd6KiYsTEW6UlWtyMTZgXI2oHK7/1p8WUagabHU1ZFT+jkExC8QG9n0M76Sq9TIynqBlfl4OOijT6NQ==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-html-support": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-html-support/-/ckeditor5-html-support-42.0.2.tgz",
+            "integrity": "sha512-z+Tg/jOf9+wzCo/NywkuHPGfOnKHfSr0hvkGjrq8b2OU9B1nJI34VTjJWSFH5NfLpn3tZo2dy3EcaoN9B7rSHA==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-engine": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0"
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-enter": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "@ckeditor/ckeditor5-image": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-image/-/ckeditor5-image-42.0.2.tgz",
+            "integrity": "sha512-RH1r10rsnEFSBNBXe3d02J6JDvoLKxwz/KCvC/EoOR4UEKDe0FNodt3+VZrb0JNqkBUIxqdtvEobXb6YmGQaDQ==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-undo": "42.0.2",
+                "@ckeditor/ckeditor5-upload": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "@ckeditor/ckeditor5-indent": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-indent/-/ckeditor5-indent-42.0.2.tgz",
+            "integrity": "sha512-qXVXqvflW8kKa7odjiSTrQtj75C5opmnGUyrM+37f7CC8OmrcjXJ5GgrFnKwHyny9YHtvQyyN+GCuzuir6a9eA==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-language": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-language/-/ckeditor5-language-42.0.2.tgz",
+            "integrity": "sha512-s0pMdNxuE+kBCFiop5Lgv/UsYAYLKCENesMXVIRrxI73GRjwJXIq5f/5a7xwvfmH3/TQT5GMrfNmf5EeYo5NHA==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-link": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-link/-/ckeditor5-link-42.0.2.tgz",
+            "integrity": "sha512-KySX11v1RyimZyc4u3AF6a/bEvA3gQg/krRsrzBbMIadtC1WN/C7w7XzjmYvx8Ui0SsH/ChBu16SxmRKO4HuTA==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "@ckeditor/ckeditor5-list": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-list/-/ckeditor5-list-42.0.2.tgz",
+            "integrity": "sha512-NTNDb01QDyjDZis8nyOsvgSNwy6YniulGDZdyeulhmFy6zyHG0GFeYA0kAyW6/bnniWyW9cpfUrAK9KTLuql4A==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-enter": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-markdown-gfm": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-markdown-gfm/-/ckeditor5-markdown-gfm-42.0.2.tgz",
+            "integrity": "sha512-mh81YHQqVF0ZVSgd7hbO3EzuM78zIhwwZiiVsJ68e4aCfpYjc3Ni1NpyORj+tian743PmFr7WAUqIePdNPmQEg==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "marked": "4.0.12",
+                "turndown": "7.2.0",
+                "turndown-plugin-gfm": "1.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-media-embed": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-media-embed/-/ckeditor5-media-embed-42.0.2.tgz",
+            "integrity": "sha512-iXGcfgOm0IWa600ln5YeSssg7Sew6Lf1z9ziTxsQsmforPIqXgZQEvdLoo0tABddSRQZI+yQZnRnwrus9sZXIA==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-undo": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-mention": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-mention/-/ckeditor5-mention-42.0.2.tgz",
+            "integrity": "sha512-81MYULfB7bHDb5Y7saIZMkNVG1BJV/ir5BwIDuuXwGXLNVX++uMTK4ryAItYToiSFN8/NBms7JFXPrRhL/zbOw==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "@ckeditor/ckeditor5-minimap": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-minimap/-/ckeditor5-minimap-42.0.2.tgz",
+            "integrity": "sha512-dOBT6bS/7tREFmpRCD4XwOEmoW4p7ZV1Pp3tA/KYQ++2BAgI/O/Yeww7nlhsKhal4r74v459hgihI/SnlfqBQA==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-page-break": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-page-break/-/ckeditor5-page-break-42.0.2.tgz",
+            "integrity": "sha512-h6Wb0fWsl4a0MyU8W3F4Yku/1CWnR6tQrcMapn0sHB9W/HAvHLQIJGdsYh+a1W6QzMIjpVAqjT4mxQ1rU86RkQ==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "ckeditor5": "42.0.2"
             }
         },
         "@ckeditor/ckeditor5-paragraph": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-40.2.0.tgz",
-            "integrity": "sha512-NotxWP1cKvbJSY1UwdTe/Oy1NnAj9Etsi4Z7XA908EvCsNSnFtzdMhYzLhFZJ18avrQFDa7PpSKSyN3M64CbSA==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-42.0.2.tgz",
+            "integrity": "sha512-feI7Rw76uPbPmoFeVEPpKdPTOjdlccpWabhfrimgT08rECLa7ErFw2oRZVmnx5+kjX+NAUeD9kaUZUUkNNP0wg==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-paste-from-office": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paste-from-office/-/ckeditor5-paste-from-office-42.0.2.tgz",
+            "integrity": "sha512-9K54E44rEjvLqWKRRHeifOlb1bICKzzX8gOv/i90sFQfMeQphA6qEn3WJZNQY4NY9Uwhu3kF/gh3/dqlcBhsvw==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-ui": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0"
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-remove-format": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-remove-format/-/ckeditor5-remove-format-42.0.2.tgz",
+            "integrity": "sha512-YIyKibU44Jt6P9qu3WGPjUUh/pb5dvexeE1XG6f5JNtVlZCy3sUI+BDytzqWI68/coOHBKYkKSDOEQdzw83PdA==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-restricted-editing": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-restricted-editing/-/ckeditor5-restricted-editing-42.0.2.tgz",
+            "integrity": "sha512-tfnEE6ieR2UhjZ9zoDNfXIMAMy2FWoajASKffdtpTMBjkVKzM+isg8j0hEkWgiQqCsJYVWt0314nPZrm5EUIfA==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
             }
         },
         "@ckeditor/ckeditor5-select-all": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-40.2.0.tgz",
-            "integrity": "sha512-yaYCqhdMcoEH3BsilhweNdbOfuO/cexQ1r1/mYoBoW4CypIuAeq8J/3qLpvFaThmCRPzJBn1J7v2Yjs/0UnamA==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-42.0.2.tgz",
+            "integrity": "sha512-eqLhxmsxDQ8s+Op4f0OoXbN9vwz0hekE1HxsClXIsqwhjsO2o/HYcyhIzR9lPgmi4bVf8uy8T9oyWQNRLv4S9w==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-show-blocks": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-show-blocks/-/ckeditor5-show-blocks-42.0.2.tgz",
+            "integrity": "sha512-CFYJN3gyiWwJ1mDonzIktRL/A+WONZuyCptELqlU51RRCwbG7eSMtu2Eyd+Q463zYbOKZcdr5uNvlWuRpSsalw==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-source-editing": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-source-editing/-/ckeditor5-source-editing-42.0.2.tgz",
+            "integrity": "sha512-lo/ZmBeAoWu9j0qfuUVIpc2QzZmcrYZ2enloz2mL22DCn3eP8IstE7gSmZlQ/DQxcPC5Sf2uC0l9IurBAP9+pg==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-theme-lark": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-special-characters": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-special-characters/-/ckeditor5-special-characters-42.0.2.tgz",
+            "integrity": "sha512-B2E9thXW0Ej1istiResH6987g+REnX18aoxW4uXG+PHDrYWjsV4fClEnjWdkO/O0A3yOoNc4LYAbGSo7z0g/1g==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2"
+            }
+        },
+        "@ckeditor/ckeditor5-style": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-style/-/ckeditor5-style-42.0.2.tgz",
+            "integrity": "sha512-vq1GSeOtZm00W4FC6MgqukJbdDE394Sh7ID6634gKmdknbxOBvNcF0XUdAu+kWtJzTjYVrC4+oPYpS5C+odidQ==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "@ckeditor/ckeditor5-table": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-table/-/ckeditor5-table-42.0.2.tgz",
+            "integrity": "sha512-fFMXbQCa7UR4aAmwVkKzDcRmKCd2YwE1iNLeGWJz7tz1c+hGeadej0aHgUxBw+hHu6DhS9AyvtwmNweQpc3PnQ==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-ui": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0"
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "@ckeditor/ckeditor5-theme-lark": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-theme-lark/-/ckeditor5-theme-lark-42.0.2.tgz",
+            "integrity": "sha512-t+/JVtK+lWzfLywsZX7eE8tfyBSnsaTsxeo84ZbSU9M1Vts5FN/5JExiY89VjsT8m84VAufbG+fDGjQpiYzsyg==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-ui": "42.0.2"
             }
         },
         "@ckeditor/ckeditor5-typing": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-40.2.0.tgz",
-            "integrity": "sha512-2E7LkmC4RHdenMUwow0EZDKxlbX00c5UHysUVT51EBGrXiJcN++0cqxQaeJzQ262oTDpk94qE5IZdGXt3ntzrw==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-42.0.2.tgz",
+            "integrity": "sha512-xwGazKjCJOQViGnk/Q0yVg98mc0aDJHvx6FsCFRF6e7B8WiMq8rPQjfO63TYOnUSOIkQJerbAv+hrsBS8XdxaQ==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-engine": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
                 "lodash-es": "4.17.21"
             }
         },
         "@ckeditor/ckeditor5-ui": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-40.2.0.tgz",
-            "integrity": "sha512-K8oC9zrJokZD5Nl4uQjJMo8Couds0eHmfNI/go6iU4A4OAdDzph+W50QnyMed4etKnMdhvUSbnuZnPtQjnsvFA==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-42.0.2.tgz",
+            "integrity": "sha512-Lrej61+xTTqIJSlA9FfqwpEClVoRabM3na8MDiWjAzneQkPgFtw1WTgUKvxNaI+eMXCmT/HVNj/RCg9vqt0pug==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
                 "color-convert": "2.0.1",
                 "color-parse": "1.4.2",
                 "lodash-es": "4.17.21",
@@ -334,79 +1567,147 @@
             }
         },
         "@ckeditor/ckeditor5-undo": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-40.2.0.tgz",
-            "integrity": "sha512-k2VZS5x4SJtYk3zhdwHYg+D00DgD0iWR0H4qQgcWmQMFRipYvXJRixP3hSLZGJciQanPFeYcjZgxNQ+rU1s8ug==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-42.0.2.tgz",
+            "integrity": "sha512-OpfdYnADY2MM8nWN5M13BEDDnwL15YHUYUpgMnydgJObZzSnePqgWQSFaBAY5j24eze0a8gyGgnOE5jV6VBm1Q==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-engine": "40.2.0",
-                "@ckeditor/ckeditor5-ui": "40.2.0"
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2"
             }
         },
         "@ckeditor/ckeditor5-upload": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-40.2.0.tgz",
-            "integrity": "sha512-AdJSKvWEQbSSyA/DfxbCHRhFN6S4ew4kuYETO57e6AS3aOuYGLBRdu9Mub7IAQcOyy1LL6ktr9u5WEOoWS2h0w==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-42.0.2.tgz",
+            "integrity": "sha512-QD6PR1ZurGQv0gULG4hNiaFMO306qM9Gin2BbICkZuJ+IFKd7nQ+mp7ZCbgPgRYtSkeUyHjSzNR4+wIA2nPVEg==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-ui": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0"
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2"
             }
         },
         "@ckeditor/ckeditor5-utils": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-40.2.0.tgz",
-            "integrity": "sha512-f+kTJBwwk7Y/LXm8pEPxBTXVlJwQrH7Levzye9zxEDB0Jtj7+brGr87o666fPmL/ATQc5M+VPhbvnk2sOv7WKg==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-42.0.2.tgz",
+            "integrity": "sha512-z4lNVoVf4cyK6cugMABNgMtYDiIK+0eQwYFtr45DhPK283RWEqrU0xwbwoqhIqeXRQ6B+9+0nC7ZIFPEdQ+iDA==",
             "dev": true,
             "requires": {
                 "lodash-es": "4.17.21"
             }
         },
         "@ckeditor/ckeditor5-watchdog": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-40.2.0.tgz",
-            "integrity": "sha512-ets7o2dUR7l23G9o/RAbu+gJzUkc2Ul269E3TEhZnbQXFjshvEGK2kzuay7I+/waL3ADuYe4zuoBqsqdPoAhfg==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-42.0.2.tgz",
+            "integrity": "sha512-0z00yqbBt/JALAD8C62LNySitQ+wBw1My43Qe2xs5VAP5tUZcziFFCc4BhMy+w6ZWUmZj2hkjSLlmx7b/vid+A==",
             "dev": true,
             "requires": {
                 "lodash-es": "4.17.21"
             }
         },
         "@ckeditor/ckeditor5-widget": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-40.2.0.tgz",
-            "integrity": "sha512-okeUSwbnu6TUKvwBOl0YdED6Me0/vvs1ybfKZPNEJNwGl989iG0LQO4oYUye8BTCZvzCZ2cBTb1Cvnwr8KRcbg==",
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-42.0.2.tgz",
+            "integrity": "sha512-ZRI8H+Ir7YpByUO4/kKMNJJE5WUDoICl1BitSR9QKmkG7X2fBRdDG8setm4HsUU1kkPe0aYy6HK2ajZ2g5ZkaA==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-engine": "40.2.0",
-                "@ckeditor/ckeditor5-enter": "40.2.0",
-                "@ckeditor/ckeditor5-typing": "40.2.0",
-                "@ckeditor/ckeditor5-ui": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-enter": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
                 "lodash-es": "4.17.21"
             }
         },
+        "@ckeditor/ckeditor5-word-count": {
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-word-count/-/ckeditor5-word-count-42.0.2.tgz",
+            "integrity": "sha512-jtlyA6TXnnRpaTgvYG219z5p+MRZWUBz3r5oHa79lFcMDREZH6gKztiE+hYSmiL2OSAtHi0kYWUAF/oJfpHt3g==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "ckeditor5": "42.0.2",
+                "lodash-es": "4.17.21"
+            }
+        },
+        "@mixmark-io/domino": {
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz",
+            "integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==",
+            "dev": true
+        },
+        "blurhash": {
+            "version": "2.0.5",
+            "resolved": "https://registry.npmjs.org/blurhash/-/blurhash-2.0.5.tgz",
+            "integrity": "sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==",
+            "dev": true
+        },
         "ckeditor5": {
-            "version": "40.2.0",
-            "resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-40.2.0.tgz",
-            "integrity": "sha512-JaFuY/6DX1wbA6yRB2xQVMr+9W1C3HvSX4AT10ccoKBKe9OctIatekDt2ztV+cMaVHLF1wocskS/Ql9XFRy2Eg==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-clipboard": "40.2.0",
-                "@ckeditor/ckeditor5-core": "40.2.0",
-                "@ckeditor/ckeditor5-engine": "40.2.0",
-                "@ckeditor/ckeditor5-enter": "40.2.0",
-                "@ckeditor/ckeditor5-paragraph": "40.2.0",
-                "@ckeditor/ckeditor5-select-all": "40.2.0",
-                "@ckeditor/ckeditor5-typing": "40.2.0",
-                "@ckeditor/ckeditor5-ui": "40.2.0",
-                "@ckeditor/ckeditor5-undo": "40.2.0",
-                "@ckeditor/ckeditor5-upload": "40.2.0",
-                "@ckeditor/ckeditor5-utils": "40.2.0",
-                "@ckeditor/ckeditor5-watchdog": "40.2.0",
-                "@ckeditor/ckeditor5-widget": "40.2.0"
+            "version": "42.0.2",
+            "resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-42.0.2.tgz",
+            "integrity": "sha512-SHyyJ6y/+2Mas3SMlVchsq1i9LYqF7J7EMwEUKAt+sIXBW9pbBnLVncXpIpGTQ/M8fS20NVk7dfJ2P4TyEZGew==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-adapter-ckfinder": "42.0.2",
+                "@ckeditor/ckeditor5-alignment": "42.0.2",
+                "@ckeditor/ckeditor5-autoformat": "42.0.2",
+                "@ckeditor/ckeditor5-autosave": "42.0.2",
+                "@ckeditor/ckeditor5-basic-styles": "42.0.2",
+                "@ckeditor/ckeditor5-block-quote": "42.0.2",
+                "@ckeditor/ckeditor5-ckbox": "42.0.2",
+                "@ckeditor/ckeditor5-ckfinder": "42.0.2",
+                "@ckeditor/ckeditor5-clipboard": "42.0.2",
+                "@ckeditor/ckeditor5-cloud-services": "42.0.2",
+                "@ckeditor/ckeditor5-code-block": "42.0.2",
+                "@ckeditor/ckeditor5-core": "42.0.2",
+                "@ckeditor/ckeditor5-easy-image": "42.0.2",
+                "@ckeditor/ckeditor5-editor-balloon": "42.0.2",
+                "@ckeditor/ckeditor5-editor-classic": "42.0.2",
+                "@ckeditor/ckeditor5-editor-decoupled": "42.0.2",
+                "@ckeditor/ckeditor5-editor-inline": "42.0.2",
+                "@ckeditor/ckeditor5-editor-multi-root": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "42.0.2",
+                "@ckeditor/ckeditor5-enter": "42.0.2",
+                "@ckeditor/ckeditor5-essentials": "42.0.2",
+                "@ckeditor/ckeditor5-find-and-replace": "42.0.2",
+                "@ckeditor/ckeditor5-font": "42.0.2",
+                "@ckeditor/ckeditor5-heading": "42.0.2",
+                "@ckeditor/ckeditor5-highlight": "42.0.2",
+                "@ckeditor/ckeditor5-horizontal-line": "42.0.2",
+                "@ckeditor/ckeditor5-html-embed": "42.0.2",
+                "@ckeditor/ckeditor5-html-support": "42.0.2",
+                "@ckeditor/ckeditor5-image": "42.0.2",
+                "@ckeditor/ckeditor5-indent": "42.0.2",
+                "@ckeditor/ckeditor5-language": "42.0.2",
+                "@ckeditor/ckeditor5-link": "42.0.2",
+                "@ckeditor/ckeditor5-list": "42.0.2",
+                "@ckeditor/ckeditor5-markdown-gfm": "42.0.2",
+                "@ckeditor/ckeditor5-media-embed": "42.0.2",
+                "@ckeditor/ckeditor5-mention": "42.0.2",
+                "@ckeditor/ckeditor5-minimap": "42.0.2",
+                "@ckeditor/ckeditor5-page-break": "42.0.2",
+                "@ckeditor/ckeditor5-paragraph": "42.0.2",
+                "@ckeditor/ckeditor5-paste-from-office": "42.0.2",
+                "@ckeditor/ckeditor5-remove-format": "42.0.2",
+                "@ckeditor/ckeditor5-restricted-editing": "42.0.2",
+                "@ckeditor/ckeditor5-select-all": "42.0.2",
+                "@ckeditor/ckeditor5-show-blocks": "42.0.2",
+                "@ckeditor/ckeditor5-source-editing": "42.0.2",
+                "@ckeditor/ckeditor5-special-characters": "42.0.2",
+                "@ckeditor/ckeditor5-style": "42.0.2",
+                "@ckeditor/ckeditor5-table": "42.0.2",
+                "@ckeditor/ckeditor5-theme-lark": "42.0.2",
+                "@ckeditor/ckeditor5-typing": "42.0.2",
+                "@ckeditor/ckeditor5-ui": "42.0.2",
+                "@ckeditor/ckeditor5-undo": "42.0.2",
+                "@ckeditor/ckeditor5-upload": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-watchdog": "42.0.2",
+                "@ckeditor/ckeditor5-widget": "42.0.2",
+                "@ckeditor/ckeditor5-word-count": "42.0.2"
             }
         },
         "color-convert": {
@@ -439,6 +1740,27 @@
             "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
             "dev": true
         },
+        "marked": {
+            "version": "4.0.12",
+            "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz",
+            "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==",
+            "dev": true
+        },
+        "turndown": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.0.tgz",
+            "integrity": "sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==",
+            "dev": true,
+            "requires": {
+                "@mixmark-io/domino": "^2.2.0"
+            }
+        },
+        "turndown-plugin-gfm": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.2.tgz",
+            "integrity": "sha512-vwz9tfvF7XN/jE0dGoBei3FXWuvll78ohzCZQuOb+ZjWrs3a0XhQVomJEb2Qh4VHTPNRO4GPZh0V7VRbiWwkRg==",
+            "dev": true
+        },
         "vanilla-colorful": {
             "version": "0.7.2",
             "resolved": "https://registry.npmjs.org/vanilla-colorful/-/vanilla-colorful-0.7.2.tgz",
diff --git a/package.json b/package.json
index 81fb811..bd524c1 100644
--- a/package.json
+++ b/package.json
@@ -3,6 +3,6 @@
         "vendor-update": "drush edit_plus:update-ckeditor-version; npm install; drush edit_plus:move-library"
     },
     "devDependencies": {
-        "@ckeditor\/ckeditor5-editor-inline": "40.2.0"
+        "@ckeditor\/ckeditor5-editor-inline": "~42.0.2"
     }
 }
\ No newline at end of file
diff --git a/src/Controller/MultipleEntityFormController.php b/src/Controller/MultipleEntityFormController.php
index ab882a9..b1d6b7b 100644
--- a/src/Controller/MultipleEntityFormController.php
+++ b/src/Controller/MultipleEntityFormController.php
@@ -84,7 +84,6 @@ final class MultipleEntityFormController extends ControllerBase {
 
     $response = new AjaxResponse();
     $response->addCommand(new AppendCommand('#toolbar-plus-sidebar', $form));
-    $response->addCommand(new InvokeCommand('#toolbar-plus-sidebar', 'show'));
 
     return $response;
   }
diff --git a/src/Drush/Commands/UpdateInlineEditor.php b/src/Drush/Commands/UpdateInlineEditor.php
index 73f6d1d..419a39b 100644
--- a/src/Drush/Commands/UpdateInlineEditor.php
+++ b/src/Drush/Commands/UpdateInlineEditor.php
@@ -17,8 +17,8 @@ final class UpdateInlineEditor extends DrushCommands {
   #[CLI\Command(name: 'edit_plus:update-ckeditor-version', aliases: ['e+_update'])]
   #[CLI\Usage(name: 'e+_update', description: 'Extracts the ckeditor version that core is currently using and updates Edit+\'s package.json.')]
   public function updateVersion() {
-    $cores_package_lock = Json::decode(file_get_contents(DRUPAL_ROOT . '/core/package-lock.json'));
-    $ckeditor5_version = $cores_package_lock['packages']['node_modules/ckeditor5']['version'];
+    $cores_packages = Json::decode(file_get_contents(DRUPAL_ROOT . '/core/package.json'));
+    $ckeditor5_version = $cores_packages['devDependencies']['ckeditor5'];
     $edit_plus_path = \Drupal::service('extension.list.module')->getPath('edit_plus'); // @todo inject.
     $package_json_path = DRUPAL_ROOT . "/$edit_plus_path/package.json";
     $edit_plus_packages = Json::decode(file_get_contents($package_json_path));
diff --git a/src/EditPlusFormTrait.php b/src/EditPlusFormTrait.php
index 2392771..09c79d1 100644
--- a/src/EditPlusFormTrait.php
+++ b/src/EditPlusFormTrait.php
@@ -141,7 +141,6 @@ trait EditPlusFormTrait {
    */
   public function addEmptyField(&$form, FormStateInterface $form_state) {
     $response = new AjaxResponse();
-    $this->messenger()->addWarning($this->t('You have unsaved changes.'));
     $this->updatePage($response, $form, $form_state);
     $this->updateForm($response, $form, $form_state);
     $this->buildBottomBar($this->getMainEntity($form, $form_state), $response);
@@ -164,7 +163,7 @@ trait EditPlusFormTrait {
     $entity = $this->getFormEntity($form, $form_state);
     $view_mode = $this->getViewMode($form, $form_state, $entity);
     $content = $this->entityContent($form, $form_state, $view_mode);
-    $selector = sprintf('[data-edit-plus-entity-wrapper="%s::%s::%s::%s"]', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity), $view_mode, $entity->bundle());
+    $selector = sprintf('[data-toolbar-plus-entity-wrapper="%s::%s::%s::%s"]', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity), $view_mode, $entity->bundle());
     $response->addCommand(new UpdateMarkup($selector, $content));
   }
 
@@ -237,8 +236,9 @@ trait EditPlusFormTrait {
         '#tree' => FALSE,
         '#attributes' => [
           'id' => self::getEditPlusFormId($entity),
-          'class' => ['edit-plus-form'],
+          'class' => ['edit-plus-form', 'toolbar-plus-sidebar'],
           'data-edit-plus-form-id' => sprintf('%s::%s', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity)),
+          'data-offset-right' => '',
         ],
         'form' => $form,
       ];
diff --git a/src/EditPlusMessagesTrait.php b/src/EditPlusMessagesTrait.php
index 68fac00..b6bb158 100644
--- a/src/EditPlusMessagesTrait.php
+++ b/src/EditPlusMessagesTrait.php
@@ -8,6 +8,8 @@ trait EditPlusMessagesTrait {
    * Clear unsaved changes message.
    */
   public function clearUnsavedChangesMessage() {
+    // @todo Remove this and update things that call it?
+    // now we are removing all of these messages in lb_plus_preprocess_status_messages
     $messenger = \Drupal::messenger();
     $all_messages = $messenger->all();
     if (!empty($all_messages['warning'])) {
diff --git a/src/EventSubscriber/CloneFieldAttribute.php b/src/EventSubscriber/CloneFieldAttribute.php
index 1445f95..a8d3973 100644
--- a/src/EventSubscriber/CloneFieldAttribute.php
+++ b/src/EventSubscriber/CloneFieldAttribute.php
@@ -14,22 +14,22 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 class CloneFieldAttribute implements EventSubscriberInterface {
 
   const DO_NOT_CLONE = [
-    'entity_autocomplete',
-    'inline_textarea',
+    'entity_reference_autocomplete_tags',
+    'text_textarea',
   ];
 
   public function addFormItemAttributesAlter(FieldAttributes $event) {
     $field_name = $event->getFieldName();
     $form = $event->getForm();
     $form_item = &$form[$field_name];
+    $widget = $event->getFormState()->get('form_display')->getComponent($field_name)['type'];
 
-    if (empty($form_item['#attributes']['data-edit-plus-clone'])) {
+    if (empty($form_item['#attributes']['data-edit-plus-clone']) && $widget) {
       $field_definition = $event->getEntity()->getFieldDefinition($field_name);
-      $clone = $this->getClonedSetting($field_definition) ?? $this->getCloneDefault($form_item, $field_definition);
+      $clone = $this->getClonedSetting($field_definition) ?? $this->getCloneDefault($widget);
       $form_item['#attributes']['data-edit-plus-clone'] = $clone;
       $event->setForm($form);
     }
-
   }
 
   private function getClonedSetting(FieldDefinitionInterface $field_definition) {
@@ -42,8 +42,17 @@ class CloneFieldAttribute implements EventSubscriberInterface {
     return NULL;
   }
 
-  private function getCloneDefault(array $form_item, FieldDefinitionInterface $field_definition) {
-    $type = edit_plus_find_widget_type($form_item, $field_definition);
+  /**
+   * Get Clone default setting.
+   *
+   * @param string $type
+   *   The widget type.
+   *
+   * @return string
+   *   Whether or not to clone the form item or move the original to the page
+   *   for editing.
+   */
+  private function getCloneDefault(string $type) {
     if (!empty($type) && in_array($type, self::DO_NOT_CLONE)) {
       return 'false';
     }
diff --git a/src/EventSubscriber/DefaultFieldAttributes.php b/src/EventSubscriber/DefaultFieldAttributes.php
index 1be1c9e..35853e9 100644
--- a/src/EventSubscriber/DefaultFieldAttributes.php
+++ b/src/EventSubscriber/DefaultFieldAttributes.php
@@ -31,7 +31,7 @@ class DefaultFieldAttributes implements EventSubscriberInterface {
     $form_item = &$form[$field_name];
     $entity = $event->getEntity();
     $form_item['#attributes']['data-edit-plus-form-item-wrapper-id'] = sprintf('%s::%s::%s::%s', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity), $field_name, 'value');
-    $form_item['#attributes']['data-edit-plus-form-item-widget'] = edit_plus_find_widget_type($form_item, $entity->getFieldDefinition($field_name));
+    $form_item['#attributes']['data-edit-plus-form-item-widget'] = $event->getFormState()->get('form_display')->getComponent($field_name)['type'];
     $form_item['#attributes']['class'][] = 'edit-plus-form-item-wrapper';
     $form_item['#attributes']['class'][] = 'edit-plus-hidden';
 
diff --git a/src/EventSubscriber/EntityTemplate.php b/src/EventSubscriber/EntityTemplate.php
deleted file mode 100644
index ddd37a9..0000000
--- a/src/EventSubscriber/EntityTemplate.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php declare(strict_types = 1);
-
-namespace Drupal\edit_plus\EventSubscriber;
-
-use Drupal\Core\Render\Markup;
-use Drupal\twig_events\Event\TwigRenderTemplateEvent;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-
-final class EntityTemplate implements EventSubscriberInterface {
-
-  public function onTwigRenderTemplate(TwigRenderTemplateEvent $event): void {
-    $variables = $event->getVariables();
-    $entity_info = $this->getEntityInfo($variables);
-    if (!empty($entity_info)) {
-      // Give the rendered entity an AJAX wrapper so it can be updated as
-      // changes are made.
-      $output = $event->getOutput();
-      $wrapped_output = sprintf('<div class="edit-plus-entity-wrapper" data-edit-plus-entity-wrapper="%s::%s::%s::%s">%s</div>', $entity_info['entity_type'], $entity_info['entity_id'], $entity_info['view_mode'], $entity_info['bundle'], $output->__toString());
-      $event->setOutput(Markup::create($wrapped_output));
-    }
-  }
-
-
-  private function getEntityInfo(array $variables) {
-    if (!empty($variables['elements']['#edit_plus_entity'])) {
-      // Regular entities.
-      return $variables['elements']['#edit_plus_entity'];
-    } elseif (!empty($variables['elements']['content']['#edit_plus_entity'])) {
-      // Inline blocks.
-      return $variables['elements']['content']['#edit_plus_entity'];
-    }
-  }
-
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getSubscribedEvents(): array {
-    return [
-      TwigRenderTemplateEvent::class => ['onTwigRenderTemplate'],
-    ];
-  }
-
-}
diff --git a/src/EventSubscriber/InlineEditorFieldAttributes.php b/src/EventSubscriber/InlineEditorFieldAttributes.php
index 63c52bb..64f1fc6 100644
--- a/src/EventSubscriber/InlineEditorFieldAttributes.php
+++ b/src/EventSubscriber/InlineEditorFieldAttributes.php
@@ -14,7 +14,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 class InlineEditorFieldAttributes implements EventSubscriberInterface {
 
   const INLINE_EDITOR_WIDGET_MAPPING = [
-    'text_format'
+    'text_textarea'
   ];
 
   /**
@@ -30,13 +30,12 @@ class InlineEditorFieldAttributes implements EventSubscriberInterface {
     $field_name = $event->getFieldName();
     $form = $event->getForm();
     $form_item = &$form[$field_name];
-    if (!empty($form_item['widget'])) {
+    $widget = $event->getFormState()->get('form_display')->getComponent($field_name)['type'];
+
+    if (in_array($widget, static::INLINE_EDITOR_WIDGET_MAPPING)) {
       foreach (Element::children($form_item['widget']) as $delta) {
         if (!empty($form_item['widget'][$delta]['#type'])) {
-          $type =& $form_item['widget'][$delta]['#type'];
-          if (in_array($type, static::INLINE_EDITOR_WIDGET_MAPPING)) {
-            $type = 'inline_textarea';
-          }
+          $form_item['widget'][$delta]['#type'] = 'inline_textarea';
         }
       }
     }
diff --git a/src/EventSubscriber/MediaFieldAttributes.php b/src/EventSubscriber/MediaFieldAttributes.php
index 9d684b7..4f44ba6 100644
--- a/src/EventSubscriber/MediaFieldAttributes.php
+++ b/src/EventSubscriber/MediaFieldAttributes.php
@@ -33,10 +33,10 @@ class MediaFieldAttributes implements EventSubscriberInterface {
       $form_item['#attributes']['data-edit-plus-handle'] = 'wrapper';
       $form_item['#attributes']['data-edit-plus-clone'] = 'true';
       $form_item['#attributes']['data-edit-plus-form-item-wrapper-id'] = sprintf('%s::%s::%s::%s', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity), $field_name, 'value');
+      $form_item['#attributes']['data-edit-plus-form-item-widget'] = $event->getFormState()->get('form_display')->getComponent($field_name)['type'];
       $form_item['widget']['#type'] = 'container';
       $form_item['widget']['#attributes']['class'][] = 'edit-plus-form-item';
       $form_item['widget']['#attributes']['data-edit-plus-form-item-id'] = sprintf('%s::%s::%s::%s::%s', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity), $field_name, 0, 'value');
-      $form_item['widget']['#attributes']['data-edit-plus-form-item-widget'] = edit_plus_find_widget_type($form_item, $entity->getFieldDefinition($field_name));
 
       $event->setForm($form);
       $event->stopPropagation();
@@ -59,15 +59,8 @@ class MediaFieldAttributes implements EventSubscriberInterface {
    *   Whether the field is a Media field.
    */
   public static function isMediaReferenceField(FieldAttributes $event): bool {
-    $entity = $event->getEntity();
-    $field_name = $event->getFieldName();
-    $field_definition = $entity->getFieldDefinition($field_name);
-    $target_type = $field_definition->getFieldStorageDefinition()->getSetting('target_type');
-    $form = $event->getForm();
-    return $target_type === 'media' &&
-      !empty($form[$field_name]['widget']['selection'][0]['#theme']) &&
-      $form[$field_name]['widget']['selection'][0]['#theme'] === 'media_library_item__widget'
-    ;
+    $widget = $event->getFormState()->get('form_display')->getComponent($event->getFieldName())['type'];
+    return $widget === 'media_library_widget';
   }
 
   /**
diff --git a/src/Form/InlineEntityFormAlter.php b/src/Form/InlineEntityFormAlter.php
index 013037f..cf36304 100644
--- a/src/Form/InlineEntityFormAlter.php
+++ b/src/Form/InlineEntityFormAlter.php
@@ -5,6 +5,7 @@ namespace Drupal\edit_plus\Form;
 use Drupal\edit_plus\Ui;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Ajax\AjaxResponse;
+use Drupal\Core\Ajax\InvokeCommand;
 use Drupal\edit_plus\EditPlusFormTrait;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Form\FormStateInterface;
@@ -76,7 +77,6 @@ class InlineEntityFormAlter implements EntityFormInterface {
   public function update(array &$form, FormStateInterface $form_state) {
     $entity = $form_state->getFormObject()->getEntity();
     $this->editPlusTempstoreRepository->set($entity);
-    $this->messenger()->addWarning($this->t('You have unsaved changes.'));
     Cache::invalidateTags([getCacheTag($entity)]);
     $form_state->setTemporaryValue('updatePage', TRUE);
 
@@ -106,6 +106,7 @@ class InlineEntityFormAlter implements EntityFormInterface {
     $this->buildBottomBar($entity, $response);
     $this->renderMessages($response);
 
+    $response->addCommand(new InvokeCommand(NULL, 'editPlusIsDoneUpdating'));
     return $response;
   }
 
diff --git a/src/ParamConverter/EntityConverter.php b/src/ParamConverter/EntityConverter.php
index a4226fa..72921a7 100644
--- a/src/ParamConverter/EntityConverter.php
+++ b/src/ParamConverter/EntityConverter.php
@@ -41,7 +41,6 @@ class EntityConverter extends EntityConverterBase {
       $entity = $tempstore_entity;
       // Flag that we have swapped this entity with a tempstore version.
       edit_plus_active_tempstore_entities($entity);
-      $this->messenger->addWarning($this->t('You have unsaved changes.'));
     }
 
     return $entity;
diff --git a/src/Plugin/Tool/EditPlus.php b/src/Plugin/Tool/EditPlus.php
index 5ab6186..0e2dd3e 100644
--- a/src/Plugin/Tool/EditPlus.php
+++ b/src/Plugin/Tool/EditPlus.php
@@ -18,7 +18,7 @@ use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
 #[Tool(
   id: 'edit_plus',
   label: new TranslatableMarkup('Edit'),
-
+  weight: 20,
 )]
 final class EditPlus extends ToolPluginBase {
 
@@ -28,8 +28,11 @@ final class EditPlus extends ToolPluginBase {
   public function getIconsPath(): array {
     $path = $this->extensionList->getPath('edit_plus');
     return [
-      'mouse_icon' => "/$path/assets/text-mouse.svg",
-      'toolbar_icon' => "/$path/assets/text-toolbar.svg"];
+      'mouse_icon' => "/$path/assets/pencil-cursor.svg",
+      'toolbar_button_icons' => [
+        'edit_plus' => "/$path/assets/pencil.svg",
+      ],
+    ];
   }
 
 }
diff --git a/src/Plugin/Tool/edit-plus.js b/src/Plugin/Tool/edit-plus.js
new file mode 100644
index 0000000..4616a33
--- /dev/null
+++ b/src/Plugin/Tool/edit-plus.js
@@ -0,0 +1,19 @@
+import * as toolPluginBase from '../../../../toolbar_plus/js/toolbar_plus/tool-plugin-base.js';
+
+(($, Drupal, once) => {
+
+  /**
+   * Edit+'s Toolbar+ plugin
+   */
+  class EditPlusPlugin extends toolPluginBase.ToolPluginBase {
+    id = 'edit_plus';
+    enable = () => {
+      Drupal.EditPlus.EnableEditMode();
+    };
+    disable = () => {
+      return Drupal.EditPlus.DisableEditMode();
+    };
+  }
+  Drupal.ToolbarPlus.PluginManager.registerPlugin(new EditPlusPlugin());
+
+})(jQuery, Drupal, once);
diff --git a/yarn.lock b/yarn.lock
index 1c79606..e6f1464 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,181 +2,747 @@
 # yarn lockfile v1
 
 
-"@ckeditor/ckeditor5-clipboard@40.2.0":
-  "integrity" "sha512-8/xPH9/i86ukcEiHdmTgNuPVJeYTrivbx5ZYqycPO4Eem7VM99gIbOe7pIYpuV+klr9ymVxIHbGyTJDJ3oUO8A=="
-  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-40.2.0.tgz"
-  "version" "40.2.0"
-  dependencies:
-    "@ckeditor/ckeditor5-core" "40.2.0"
-    "@ckeditor/ckeditor5-engine" "40.2.0"
-    "@ckeditor/ckeditor5-ui" "40.2.0"
-    "@ckeditor/ckeditor5-utils" "40.2.0"
-    "@ckeditor/ckeditor5-widget" "40.2.0"
-    "lodash-es" "4.17.21"
-
-"@ckeditor/ckeditor5-core@40.2.0":
-  "integrity" "sha512-0fqIaN+ZhkXXA3mpBN+alycBzPMc8ruO8VrP0OnvCjowqZVS2HXC2AaXNBdxc75xGI3ScXIor7FsgFHxVJIYYQ=="
-  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-40.2.0.tgz"
-  "version" "40.2.0"
-  dependencies:
-    "@ckeditor/ckeditor5-engine" "40.2.0"
-    "@ckeditor/ckeditor5-utils" "40.2.0"
-    "lodash-es" "4.17.21"
-
-"@ckeditor/ckeditor5-editor-inline@40.2.0":
-  "integrity" "sha512-Ox9lQiCSv0acyKaQLCcoebBjAMRE6L6iCBN8XVeQ3u91KZV6/LOhP+CJ314c8AuH+UHPeJt9MHP6eGU0trKHGQ=="
-  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-inline/-/ckeditor5-editor-inline-40.2.0.tgz"
-  "version" "40.2.0"
-  dependencies:
-    "ckeditor5" "40.2.0"
-    "lodash-es" "4.17.21"
-
-"@ckeditor/ckeditor5-engine@40.2.0":
-  "integrity" "sha512-sgboUX8Ps+LcEgywyT3BeK1nzLHjNVIiZU1qvRxR3ixzIw4w2xRNXCGfESWLW5Y5rv9+ypUCrX61oLnZU64PQQ=="
-  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-40.2.0.tgz"
-  "version" "40.2.0"
-  dependencies:
-    "@ckeditor/ckeditor5-utils" "40.2.0"
-    "lodash-es" "4.17.21"
-
-"@ckeditor/ckeditor5-enter@40.2.0":
-  "integrity" "sha512-GjTRaKNX8QEDJ3YYKG3GfPZfGHrcigGBxbo+1WDT7NaOsR2DA/CIZfHlAPfgJDAMV17bhWsT3gy3+oQZsExtnQ=="
-  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-40.2.0.tgz"
-  "version" "40.2.0"
-  dependencies:
-    "@ckeditor/ckeditor5-core" "40.2.0"
-    "@ckeditor/ckeditor5-engine" "40.2.0"
-    "@ckeditor/ckeditor5-utils" "40.2.0"
-
-"@ckeditor/ckeditor5-paragraph@40.2.0":
-  "integrity" "sha512-NotxWP1cKvbJSY1UwdTe/Oy1NnAj9Etsi4Z7XA908EvCsNSnFtzdMhYzLhFZJ18avrQFDa7PpSKSyN3M64CbSA=="
-  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-40.2.0.tgz"
-  "version" "40.2.0"
-  dependencies:
-    "@ckeditor/ckeditor5-core" "40.2.0"
-    "@ckeditor/ckeditor5-ui" "40.2.0"
-    "@ckeditor/ckeditor5-utils" "40.2.0"
-
-"@ckeditor/ckeditor5-select-all@40.2.0":
-  "integrity" "sha512-yaYCqhdMcoEH3BsilhweNdbOfuO/cexQ1r1/mYoBoW4CypIuAeq8J/3qLpvFaThmCRPzJBn1J7v2Yjs/0UnamA=="
-  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-40.2.0.tgz"
-  "version" "40.2.0"
-  dependencies:
-    "@ckeditor/ckeditor5-core" "40.2.0"
-    "@ckeditor/ckeditor5-ui" "40.2.0"
-    "@ckeditor/ckeditor5-utils" "40.2.0"
-
-"@ckeditor/ckeditor5-typing@40.2.0":
-  "integrity" "sha512-2E7LkmC4RHdenMUwow0EZDKxlbX00c5UHysUVT51EBGrXiJcN++0cqxQaeJzQ262oTDpk94qE5IZdGXt3ntzrw=="
-  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-40.2.0.tgz"
-  "version" "40.2.0"
-  dependencies:
-    "@ckeditor/ckeditor5-core" "40.2.0"
-    "@ckeditor/ckeditor5-engine" "40.2.0"
-    "@ckeditor/ckeditor5-utils" "40.2.0"
-    "lodash-es" "4.17.21"
-
-"@ckeditor/ckeditor5-ui@40.2.0":
-  "integrity" "sha512-K8oC9zrJokZD5Nl4uQjJMo8Couds0eHmfNI/go6iU4A4OAdDzph+W50QnyMed4etKnMdhvUSbnuZnPtQjnsvFA=="
-  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-40.2.0.tgz"
-  "version" "40.2.0"
-  dependencies:
-    "@ckeditor/ckeditor5-core" "40.2.0"
-    "@ckeditor/ckeditor5-utils" "40.2.0"
-    "color-convert" "2.0.1"
-    "color-parse" "1.4.2"
-    "lodash-es" "4.17.21"
-    "vanilla-colorful" "0.7.2"
-
-"@ckeditor/ckeditor5-undo@40.2.0":
-  "integrity" "sha512-k2VZS5x4SJtYk3zhdwHYg+D00DgD0iWR0H4qQgcWmQMFRipYvXJRixP3hSLZGJciQanPFeYcjZgxNQ+rU1s8ug=="
-  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-40.2.0.tgz"
-  "version" "40.2.0"
-  dependencies:
-    "@ckeditor/ckeditor5-core" "40.2.0"
-    "@ckeditor/ckeditor5-engine" "40.2.0"
-    "@ckeditor/ckeditor5-ui" "40.2.0"
-
-"@ckeditor/ckeditor5-upload@40.2.0":
-  "integrity" "sha512-AdJSKvWEQbSSyA/DfxbCHRhFN6S4ew4kuYETO57e6AS3aOuYGLBRdu9Mub7IAQcOyy1LL6ktr9u5WEOoWS2h0w=="
-  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-40.2.0.tgz"
-  "version" "40.2.0"
-  dependencies:
-    "@ckeditor/ckeditor5-core" "40.2.0"
-    "@ckeditor/ckeditor5-ui" "40.2.0"
-    "@ckeditor/ckeditor5-utils" "40.2.0"
-
-"@ckeditor/ckeditor5-utils@40.2.0":
-  "integrity" "sha512-f+kTJBwwk7Y/LXm8pEPxBTXVlJwQrH7Levzye9zxEDB0Jtj7+brGr87o666fPmL/ATQc5M+VPhbvnk2sOv7WKg=="
-  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-40.2.0.tgz"
-  "version" "40.2.0"
-  dependencies:
-    "lodash-es" "4.17.21"
-
-"@ckeditor/ckeditor5-watchdog@40.2.0":
-  "integrity" "sha512-ets7o2dUR7l23G9o/RAbu+gJzUkc2Ul269E3TEhZnbQXFjshvEGK2kzuay7I+/waL3ADuYe4zuoBqsqdPoAhfg=="
-  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-40.2.0.tgz"
-  "version" "40.2.0"
-  dependencies:
-    "lodash-es" "4.17.21"
-
-"@ckeditor/ckeditor5-widget@40.2.0":
-  "integrity" "sha512-okeUSwbnu6TUKvwBOl0YdED6Me0/vvs1ybfKZPNEJNwGl989iG0LQO4oYUye8BTCZvzCZ2cBTb1Cvnwr8KRcbg=="
-  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-40.2.0.tgz"
-  "version" "40.2.0"
-  dependencies:
-    "@ckeditor/ckeditor5-core" "40.2.0"
-    "@ckeditor/ckeditor5-engine" "40.2.0"
-    "@ckeditor/ckeditor5-enter" "40.2.0"
-    "@ckeditor/ckeditor5-typing" "40.2.0"
-    "@ckeditor/ckeditor5-ui" "40.2.0"
-    "@ckeditor/ckeditor5-utils" "40.2.0"
-    "lodash-es" "4.17.21"
-
-"ckeditor5@40.2.0":
-  "integrity" "sha512-JaFuY/6DX1wbA6yRB2xQVMr+9W1C3HvSX4AT10ccoKBKe9OctIatekDt2ztV+cMaVHLF1wocskS/Ql9XFRy2Eg=="
-  "resolved" "https://registry.npmjs.org/ckeditor5/-/ckeditor5-40.2.0.tgz"
-  "version" "40.2.0"
-  dependencies:
-    "@ckeditor/ckeditor5-clipboard" "40.2.0"
-    "@ckeditor/ckeditor5-core" "40.2.0"
-    "@ckeditor/ckeditor5-engine" "40.2.0"
-    "@ckeditor/ckeditor5-enter" "40.2.0"
-    "@ckeditor/ckeditor5-paragraph" "40.2.0"
-    "@ckeditor/ckeditor5-select-all" "40.2.0"
-    "@ckeditor/ckeditor5-typing" "40.2.0"
-    "@ckeditor/ckeditor5-ui" "40.2.0"
-    "@ckeditor/ckeditor5-undo" "40.2.0"
-    "@ckeditor/ckeditor5-upload" "40.2.0"
-    "@ckeditor/ckeditor5-utils" "40.2.0"
-    "@ckeditor/ckeditor5-watchdog" "40.2.0"
-    "@ckeditor/ckeditor5-widget" "40.2.0"
-
-"color-convert@2.0.1":
-  "integrity" "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="
-  "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz"
-  "version" "2.0.1"
-  dependencies:
-    "color-name" "~1.1.4"
-
-"color-name@^1.0.0", "color-name@~1.1.4":
-  "integrity" "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
-  "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
-  "version" "1.1.4"
-
-"color-parse@1.4.2":
-  "integrity" "sha512-RI7s49/8yqDj3fECFZjUI1Yi0z/Gq1py43oNJivAIIDSyJiOZLfYCRQEgn8HEVAj++PcRe8AnL2XF0fRJ3BTnA=="
-  "resolved" "https://registry.npmjs.org/color-parse/-/color-parse-1.4.2.tgz"
-  "version" "1.4.2"
-  dependencies:
-    "color-name" "^1.0.0"
-
-"lodash-es@4.17.21":
-  "integrity" "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
-  "resolved" "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz"
-  "version" "4.17.21"
-
-"vanilla-colorful@0.7.2":
-  "integrity" "sha512-z2YZusTFC6KnLERx1cgoIRX2CjPRP0W75N+3CC6gbvdX5Ch47rZkEMGO2Xnf+IEmi3RiFLxS18gayMA27iU7Kg=="
-  "resolved" "https://registry.npmjs.org/vanilla-colorful/-/vanilla-colorful-0.7.2.tgz"
-  "version" "0.7.2"
+"@ckeditor/ckeditor5-adapter-ckfinder@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-adapter-ckfinder/-/ckeditor5-adapter-ckfinder-42.0.2.tgz"
+  integrity sha512-nX624WYyyJh6BGGy7jNOlEyf+Kv95VWHKlqn39HLTLKlONBp3zBhAtN9rd0gqU5EM6FgPQ+RjOtQinuto0B6oQ==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-upload" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-alignment@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-alignment/-/ckeditor5-alignment-42.0.2.tgz"
+  integrity sha512-g6I0f5Ko7tckHrKYyZhNQL3dGHTcMbjypIfEkk3SAv68X4bDKLImVUJ1L6y0aZnGNoI40cMr0byEyln5rOq67Q==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-autoformat@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-autoformat/-/ckeditor5-autoformat-42.0.2.tgz"
+  integrity sha512-tnMdNc8VJ4y4wqbkSAbBGRiUukByOo1nBqyvzYS+SZ2Wzo67OmzKybvqz60PFYIbPAQJa0/uFkvgd55c+VTaqg==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-typing" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-autosave@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-autosave/-/ckeditor5-autosave-42.0.2.tgz"
+  integrity sha512-QIsftrJ6LjJrmUTDfJYpBKy9DJ79ltt2pMHtb8DhoyugGZUup40pFvMrt/4/UuQRm64jS/IjhwWXkSMg4PejJw==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-basic-styles@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-basic-styles/-/ckeditor5-basic-styles-42.0.2.tgz"
+  integrity sha512-LT0Kk1K30z/YhI48QBDa69tjU1G2ljSKi5pU5pfiSBLhMl1ShLmXIAy6cEHnijHS0mte8FGwhiGXmNB/jAZ7Iw==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-typing" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-block-quote@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-block-quote/-/ckeditor5-block-quote-42.0.2.tgz"
+  integrity sha512-xfX+tdAhn7WPHNNZR5Wkjl+OnmbNlEOVVZCL2iAjfswf4r3CglLnJOa529FO+4MyNcwkP+joQ3iVBclZNbETLw==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-enter" "42.0.2"
+    "@ckeditor/ckeditor5-typing" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-ckbox@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-ckbox/-/ckeditor5-ckbox-42.0.2.tgz"
+  integrity sha512-RvCUphlhrTuGBy78kEOFJvdvmP3o7ajibubOOpVfUMz1V8BbTmmx1+XaveCDxznkwiCLUwqZplWZnpPoEABj2w==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-upload" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    blurhash "2.0.5"
+    ckeditor5 "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-ckfinder@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-ckfinder/-/ckeditor5-ckfinder-42.0.2.tgz"
+  integrity sha512-3lkMF+9Z3R1OUfwZJdORlRDgPSyR9Be57zgizpevpKTenxrZ+UU33ib/kvK8LXVDOzz3qp7UyCucLfY1KNXCzA==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-clipboard@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-42.0.2.tgz"
+  integrity sha512-x76SjAhaguwVQtJSgz62q96RsJsw0eSM7ZnuUqLjMMzO+hq2hAj7ZIJNPcA46ZyDR6LDQzH760IumSz0xlHn9w==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    "@ckeditor/ckeditor5-widget" "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-cloud-services@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-cloud-services/-/ckeditor5-cloud-services-42.0.2.tgz"
+  integrity sha512-oNdtgD/suEh5nAndXsjik8HgRDk095EGxkmrMO+Z3gbOit28fvTDL6bbUOQvenoNNWa7RXLZMbfyiTMuNH+X8Q==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-code-block@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-code-block/-/ckeditor5-code-block-42.0.2.tgz"
+  integrity sha512-NFGn+350VS6/UNhHm9CurOLm3ZiXFUCO/SgKRILPKZ82Wh2GQqocs5O3yvvo1WQ9jA2DEwjfN0TgOpwgVOZQPQ==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-enter" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-core@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-42.0.2.tgz"
+  integrity sha512-LkNx1Qpk/gwh0wYkl4FdZfi1N2G5Gmp026sVp301boyE9sSVeR3YxcSdKXfsr2HII+7EdJHxMswTvnd/L+IdSg==
+  dependencies:
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    "@ckeditor/ckeditor5-watchdog" "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-easy-image@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-easy-image/-/ckeditor5-easy-image-42.0.2.tgz"
+  integrity sha512-JYVpX6lRVRve8roROx5y6nsixLXLuVwIokBLoo+usS313xeeZvjoLrxGTeRuyyVbK3BFPE+zqyXsgqGs1Q0stg==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-upload" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-editor-balloon@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-balloon/-/ckeditor5-editor-balloon-42.0.2.tgz"
+  integrity sha512-NXTVQ3aBW8OirKgv8PJvjSDDbl39JGlnS/W+/LRwUlOgHVVWHVSMMqY52AhP90TzP6xfbFYBYX8n13EB6o/4Bw==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-editor-classic@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-classic/-/ckeditor5-editor-classic-42.0.2.tgz"
+  integrity sha512-K9+154AP/OpxDn6702772QCiT830lAQXsiUty1Z35MM3hVS5quwkuxS6V0NjKxx0AcqUmmgdXoFxx6v4mj3R7g==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-editor-decoupled@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-decoupled/-/ckeditor5-editor-decoupled-42.0.2.tgz"
+  integrity sha512-ANhlpcZXV+nZl/f9o+wS5vqc+Va5K4LnYA0F/pJNTNlighVCa1nGQX11tRGm48vItpNlgQxty+p86NHa+7YrLw==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-editor-inline@~42.0.2", "@ckeditor/ckeditor5-editor-inline@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-inline/-/ckeditor5-editor-inline-42.0.2.tgz"
+  integrity sha512-gWngpGE/6JDCyKpKTX7iIgFaxrDPzocZt56p1JmBJCNpVQb4sGoZs94uUg7rxlVo8t3PDH+foL49gSdBKYS9uw==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-editor-multi-root@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-multi-root/-/ckeditor5-editor-multi-root-42.0.2.tgz"
+  integrity sha512-1Cv4WGB75KoWZWewCOnHP4s4HGFXKt3BajvDkN8LXS6CtaIPDkH18okY/ivH/Idhu1pT9k2bjzCfR7W4EhtRJg==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-engine@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-42.0.2.tgz"
+  integrity sha512-mI4+X6Z0ihnyAKzka5RjoUgZoaRDckMniN8LLYNum3ewz+KWIVjtHn6NBrqEqw24BpwYfSVEPL/NdgA6xl93Jw==
+  dependencies:
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-enter@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-42.0.2.tgz"
+  integrity sha512-pzVXQPdBgskiqVpCG/yxliuEXPECCI3GJ/OF5wXs2GQ04IcqBz5FsazUtSLS5nnA4e3YpcdzzEC0Kn1ASdl7QQ==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+
+"@ckeditor/ckeditor5-essentials@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-essentials/-/ckeditor5-essentials-42.0.2.tgz"
+  integrity sha512-4qhW/7zm69KHnotKEs05YB6YTD6WB6QWJ6U44V6dFGJUUUmYN1fOt9ri6lU8snUVhJrU0C9IuGpVkb8Aby79GQ==
+  dependencies:
+    "@ckeditor/ckeditor5-clipboard" "42.0.2"
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-enter" "42.0.2"
+    "@ckeditor/ckeditor5-select-all" "42.0.2"
+    "@ckeditor/ckeditor5-typing" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-undo" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-find-and-replace@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-find-and-replace/-/ckeditor5-find-and-replace-42.0.2.tgz"
+  integrity sha512-9Fc5nKUhDtivHxGoY5nEvwjqUyvMwcNs1Xo6nt9aXeG0gd4mrCdUQaQfRIlcycLmeVD1MgKfWh7sOv+EtuYFRA==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-font@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-font/-/ckeditor5-font-42.0.2.tgz"
+  integrity sha512-Soj1auf82Zz6y56qKf6nV6RSjNPENZm9vpkJ9jhyQ4pMh6YvQ7EkzbOwPCoskXm+ab8EAuH+bjS0n5lewN5i7Q==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-heading@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-heading/-/ckeditor5-heading-42.0.2.tgz"
+  integrity sha512-1lwxsxzJRikSerwhH1By9FlAO2EQhcrt3xnpxBFME3pS2Y6tbkHj81W5Lu2cf+0ew5Bzcp5uqTvaArRtVssY1A==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-paragraph" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-highlight@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-highlight/-/ckeditor5-highlight-42.0.2.tgz"
+  integrity sha512-I/qVqC1YS6Hfg1dZjP665NU2fIx5Dk4Rjq2ku7yxQrsmG+rle2xrEzXF1BsaBeK6ko+fX7JaP86dTvywnnOeaw==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-horizontal-line@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-horizontal-line/-/ckeditor5-horizontal-line-42.0.2.tgz"
+  integrity sha512-zXnK2k5F5lhbLVwHzyURPMRGc8pc1YPz8fYXmz1pf/JG/EgXGGuUlczkpzegBUb9MctFgZbs09xIkTkVBQZmNw==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-widget" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-html-embed@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-html-embed/-/ckeditor5-html-embed-42.0.2.tgz"
+  integrity sha512-aqCV9vQJd6KiYsTEW6UlWtyMTZgXI2oHK7/1p8WUagabHU1ZFT+jkExC8QG9n0M76Sq9TIynqBlfl4OOijT6NQ==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    "@ckeditor/ckeditor5-widget" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-html-support@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-html-support/-/ckeditor5-html-support-42.0.2.tgz"
+  integrity sha512-z+Tg/jOf9+wzCo/NywkuHPGfOnKHfSr0hvkGjrq8b2OU9B1nJI34VTjJWSFH5NfLpn3tZo2dy3EcaoN9B7rSHA==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-enter" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    "@ckeditor/ckeditor5-widget" "42.0.2"
+    ckeditor5 "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-image@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-image/-/ckeditor5-image-42.0.2.tgz"
+  integrity sha512-RH1r10rsnEFSBNBXe3d02J6JDvoLKxwz/KCvC/EoOR4UEKDe0FNodt3+VZrb0JNqkBUIxqdtvEobXb6YmGQaDQ==
+  dependencies:
+    "@ckeditor/ckeditor5-clipboard" "42.0.2"
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-typing" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-undo" "42.0.2"
+    "@ckeditor/ckeditor5-upload" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    "@ckeditor/ckeditor5-widget" "42.0.2"
+    ckeditor5 "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-indent@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-indent/-/ckeditor5-indent-42.0.2.tgz"
+  integrity sha512-qXVXqvflW8kKa7odjiSTrQtj75C5opmnGUyrM+37f7CC8OmrcjXJ5GgrFnKwHyny9YHtvQyyN+GCuzuir6a9eA==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-language@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-language/-/ckeditor5-language-42.0.2.tgz"
+  integrity sha512-s0pMdNxuE+kBCFiop5Lgv/UsYAYLKCENesMXVIRrxI73GRjwJXIq5f/5a7xwvfmH3/TQT5GMrfNmf5EeYo5NHA==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-link@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-link/-/ckeditor5-link-42.0.2.tgz"
+  integrity sha512-KySX11v1RyimZyc4u3AF6a/bEvA3gQg/krRsrzBbMIadtC1WN/C7w7XzjmYvx8Ui0SsH/ChBu16SxmRKO4HuTA==
+  dependencies:
+    "@ckeditor/ckeditor5-clipboard" "42.0.2"
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-typing" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    "@ckeditor/ckeditor5-widget" "42.0.2"
+    ckeditor5 "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-list@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-list/-/ckeditor5-list-42.0.2.tgz"
+  integrity sha512-NTNDb01QDyjDZis8nyOsvgSNwy6YniulGDZdyeulhmFy6zyHG0GFeYA0kAyW6/bnniWyW9cpfUrAK9KTLuql4A==
+  dependencies:
+    "@ckeditor/ckeditor5-clipboard" "42.0.2"
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-enter" "42.0.2"
+    "@ckeditor/ckeditor5-typing" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-markdown-gfm@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-markdown-gfm/-/ckeditor5-markdown-gfm-42.0.2.tgz"
+  integrity sha512-mh81YHQqVF0ZVSgd7hbO3EzuM78zIhwwZiiVsJ68e4aCfpYjc3Ni1NpyORj+tian743PmFr7WAUqIePdNPmQEg==
+  dependencies:
+    "@ckeditor/ckeditor5-clipboard" "42.0.2"
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    ckeditor5 "42.0.2"
+    marked "4.0.12"
+    turndown "7.2.0"
+    turndown-plugin-gfm "1.0.2"
+
+"@ckeditor/ckeditor5-media-embed@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-media-embed/-/ckeditor5-media-embed-42.0.2.tgz"
+  integrity sha512-iXGcfgOm0IWa600ln5YeSssg7Sew6Lf1z9ziTxsQsmforPIqXgZQEvdLoo0tABddSRQZI+yQZnRnwrus9sZXIA==
+  dependencies:
+    "@ckeditor/ckeditor5-clipboard" "42.0.2"
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-typing" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-undo" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    "@ckeditor/ckeditor5-widget" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-mention@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-mention/-/ckeditor5-mention-42.0.2.tgz"
+  integrity sha512-81MYULfB7bHDb5Y7saIZMkNVG1BJV/ir5BwIDuuXwGXLNVX++uMTK4ryAItYToiSFN8/NBms7JFXPrRhL/zbOw==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-typing" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-minimap@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-minimap/-/ckeditor5-minimap-42.0.2.tgz"
+  integrity sha512-dOBT6bS/7tREFmpRCD4XwOEmoW4p7ZV1Pp3tA/KYQ++2BAgI/O/Yeww7nlhsKhal4r74v459hgihI/SnlfqBQA==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-page-break@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-page-break/-/ckeditor5-page-break-42.0.2.tgz"
+  integrity sha512-h6Wb0fWsl4a0MyU8W3F4Yku/1CWnR6tQrcMapn0sHB9W/HAvHLQIJGdsYh+a1W6QzMIjpVAqjT4mxQ1rU86RkQ==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-widget" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-paragraph@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-42.0.2.tgz"
+  integrity sha512-feI7Rw76uPbPmoFeVEPpKdPTOjdlccpWabhfrimgT08rECLa7ErFw2oRZVmnx5+kjX+NAUeD9kaUZUUkNNP0wg==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+
+"@ckeditor/ckeditor5-paste-from-office@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-paste-from-office/-/ckeditor5-paste-from-office-42.0.2.tgz"
+  integrity sha512-9K54E44rEjvLqWKRRHeifOlb1bICKzzX8gOv/i90sFQfMeQphA6qEn3WJZNQY4NY9Uwhu3kF/gh3/dqlcBhsvw==
+  dependencies:
+    "@ckeditor/ckeditor5-clipboard" "42.0.2"
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-remove-format@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-remove-format/-/ckeditor5-remove-format-42.0.2.tgz"
+  integrity sha512-YIyKibU44Jt6P9qu3WGPjUUh/pb5dvexeE1XG6f5JNtVlZCy3sUI+BDytzqWI68/coOHBKYkKSDOEQdzw83PdA==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-restricted-editing@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-restricted-editing/-/ckeditor5-restricted-editing-42.0.2.tgz"
+  integrity sha512-tfnEE6ieR2UhjZ9zoDNfXIMAMy2FWoajASKffdtpTMBjkVKzM+isg8j0hEkWgiQqCsJYVWt0314nPZrm5EUIfA==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-select-all@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-42.0.2.tgz"
+  integrity sha512-eqLhxmsxDQ8s+Op4f0OoXbN9vwz0hekE1HxsClXIsqwhjsO2o/HYcyhIzR9lPgmi4bVf8uy8T9oyWQNRLv4S9w==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+
+"@ckeditor/ckeditor5-show-blocks@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-show-blocks/-/ckeditor5-show-blocks-42.0.2.tgz"
+  integrity sha512-CFYJN3gyiWwJ1mDonzIktRL/A+WONZuyCptELqlU51RRCwbG7eSMtu2Eyd+Q463zYbOKZcdr5uNvlWuRpSsalw==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-source-editing@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-source-editing/-/ckeditor5-source-editing-42.0.2.tgz"
+  integrity sha512-lo/ZmBeAoWu9j0qfuUVIpc2QzZmcrYZ2enloz2mL22DCn3eP8IstE7gSmZlQ/DQxcPC5Sf2uC0l9IurBAP9+pg==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-theme-lark" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-special-characters@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-special-characters/-/ckeditor5-special-characters-42.0.2.tgz"
+  integrity sha512-B2E9thXW0Ej1istiResH6987g+REnX18aoxW4uXG+PHDrYWjsV4fClEnjWdkO/O0A3yOoNc4LYAbGSo7z0g/1g==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-typing" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+
+"@ckeditor/ckeditor5-style@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-style/-/ckeditor5-style-42.0.2.tgz"
+  integrity sha512-vq1GSeOtZm00W4FC6MgqukJbdDE394Sh7ID6634gKmdknbxOBvNcF0XUdAu+kWtJzTjYVrC4+oPYpS5C+odidQ==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-typing" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-table@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-table/-/ckeditor5-table-42.0.2.tgz"
+  integrity sha512-fFMXbQCa7UR4aAmwVkKzDcRmKCd2YwE1iNLeGWJz7tz1c+hGeadej0aHgUxBw+hHu6DhS9AyvtwmNweQpc3PnQ==
+  dependencies:
+    "@ckeditor/ckeditor5-clipboard" "42.0.2"
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    "@ckeditor/ckeditor5-widget" "42.0.2"
+    ckeditor5 "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-theme-lark@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-theme-lark/-/ckeditor5-theme-lark-42.0.2.tgz"
+  integrity sha512-t+/JVtK+lWzfLywsZX7eE8tfyBSnsaTsxeo84ZbSU9M1Vts5FN/5JExiY89VjsT8m84VAufbG+fDGjQpiYzsyg==
+  dependencies:
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+
+"@ckeditor/ckeditor5-typing@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-42.0.2.tgz"
+  integrity sha512-xwGazKjCJOQViGnk/Q0yVg98mc0aDJHvx6FsCFRF6e7B8WiMq8rPQjfO63TYOnUSOIkQJerbAv+hrsBS8XdxaQ==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-ui@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-42.0.2.tgz"
+  integrity sha512-Lrej61+xTTqIJSlA9FfqwpEClVoRabM3na8MDiWjAzneQkPgFtw1WTgUKvxNaI+eMXCmT/HVNj/RCg9vqt0pug==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    color-convert "2.0.1"
+    color-parse "1.4.2"
+    lodash-es "4.17.21"
+    vanilla-colorful "0.7.2"
+
+"@ckeditor/ckeditor5-undo@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-42.0.2.tgz"
+  integrity sha512-OpfdYnADY2MM8nWN5M13BEDDnwL15YHUYUpgMnydgJObZzSnePqgWQSFaBAY5j24eze0a8gyGgnOE5jV6VBm1Q==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+
+"@ckeditor/ckeditor5-upload@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-42.0.2.tgz"
+  integrity sha512-QD6PR1ZurGQv0gULG4hNiaFMO306qM9Gin2BbICkZuJ+IFKd7nQ+mp7ZCbgPgRYtSkeUyHjSzNR4+wIA2nPVEg==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+
+"@ckeditor/ckeditor5-utils@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-42.0.2.tgz"
+  integrity sha512-z4lNVoVf4cyK6cugMABNgMtYDiIK+0eQwYFtr45DhPK283RWEqrU0xwbwoqhIqeXRQ6B+9+0nC7ZIFPEdQ+iDA==
+  dependencies:
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-watchdog@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-42.0.2.tgz"
+  integrity sha512-0z00yqbBt/JALAD8C62LNySitQ+wBw1My43Qe2xs5VAP5tUZcziFFCc4BhMy+w6ZWUmZj2hkjSLlmx7b/vid+A==
+  dependencies:
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-widget@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-42.0.2.tgz"
+  integrity sha512-ZRI8H+Ir7YpByUO4/kKMNJJE5WUDoICl1BitSR9QKmkG7X2fBRdDG8setm4HsUU1kkPe0aYy6HK2ajZ2g5ZkaA==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-enter" "42.0.2"
+    "@ckeditor/ckeditor5-typing" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    lodash-es "4.17.21"
+
+"@ckeditor/ckeditor5-word-count@42.0.2":
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-word-count/-/ckeditor5-word-count-42.0.2.tgz"
+  integrity sha512-jtlyA6TXnnRpaTgvYG219z5p+MRZWUBz3r5oHa79lFcMDREZH6gKztiE+hYSmiL2OSAtHi0kYWUAF/oJfpHt3g==
+  dependencies:
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    ckeditor5 "42.0.2"
+    lodash-es "4.17.21"
+
+"@mixmark-io/domino@^2.2.0":
+  version "2.2.0"
+  resolved "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz"
+  integrity sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==
+
+blurhash@2.0.5:
+  version "2.0.5"
+  resolved "https://registry.npmjs.org/blurhash/-/blurhash-2.0.5.tgz"
+  integrity sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==
+
+ckeditor5@42.0.2:
+  version "42.0.2"
+  resolved "https://registry.npmjs.org/ckeditor5/-/ckeditor5-42.0.2.tgz"
+  integrity sha512-SHyyJ6y/+2Mas3SMlVchsq1i9LYqF7J7EMwEUKAt+sIXBW9pbBnLVncXpIpGTQ/M8fS20NVk7dfJ2P4TyEZGew==
+  dependencies:
+    "@ckeditor/ckeditor5-adapter-ckfinder" "42.0.2"
+    "@ckeditor/ckeditor5-alignment" "42.0.2"
+    "@ckeditor/ckeditor5-autoformat" "42.0.2"
+    "@ckeditor/ckeditor5-autosave" "42.0.2"
+    "@ckeditor/ckeditor5-basic-styles" "42.0.2"
+    "@ckeditor/ckeditor5-block-quote" "42.0.2"
+    "@ckeditor/ckeditor5-ckbox" "42.0.2"
+    "@ckeditor/ckeditor5-ckfinder" "42.0.2"
+    "@ckeditor/ckeditor5-clipboard" "42.0.2"
+    "@ckeditor/ckeditor5-cloud-services" "42.0.2"
+    "@ckeditor/ckeditor5-code-block" "42.0.2"
+    "@ckeditor/ckeditor5-core" "42.0.2"
+    "@ckeditor/ckeditor5-easy-image" "42.0.2"
+    "@ckeditor/ckeditor5-editor-balloon" "42.0.2"
+    "@ckeditor/ckeditor5-editor-classic" "42.0.2"
+    "@ckeditor/ckeditor5-editor-decoupled" "42.0.2"
+    "@ckeditor/ckeditor5-editor-inline" "42.0.2"
+    "@ckeditor/ckeditor5-editor-multi-root" "42.0.2"
+    "@ckeditor/ckeditor5-engine" "42.0.2"
+    "@ckeditor/ckeditor5-enter" "42.0.2"
+    "@ckeditor/ckeditor5-essentials" "42.0.2"
+    "@ckeditor/ckeditor5-find-and-replace" "42.0.2"
+    "@ckeditor/ckeditor5-font" "42.0.2"
+    "@ckeditor/ckeditor5-heading" "42.0.2"
+    "@ckeditor/ckeditor5-highlight" "42.0.2"
+    "@ckeditor/ckeditor5-horizontal-line" "42.0.2"
+    "@ckeditor/ckeditor5-html-embed" "42.0.2"
+    "@ckeditor/ckeditor5-html-support" "42.0.2"
+    "@ckeditor/ckeditor5-image" "42.0.2"
+    "@ckeditor/ckeditor5-indent" "42.0.2"
+    "@ckeditor/ckeditor5-language" "42.0.2"
+    "@ckeditor/ckeditor5-link" "42.0.2"
+    "@ckeditor/ckeditor5-list" "42.0.2"
+    "@ckeditor/ckeditor5-markdown-gfm" "42.0.2"
+    "@ckeditor/ckeditor5-media-embed" "42.0.2"
+    "@ckeditor/ckeditor5-mention" "42.0.2"
+    "@ckeditor/ckeditor5-minimap" "42.0.2"
+    "@ckeditor/ckeditor5-page-break" "42.0.2"
+    "@ckeditor/ckeditor5-paragraph" "42.0.2"
+    "@ckeditor/ckeditor5-paste-from-office" "42.0.2"
+    "@ckeditor/ckeditor5-remove-format" "42.0.2"
+    "@ckeditor/ckeditor5-restricted-editing" "42.0.2"
+    "@ckeditor/ckeditor5-select-all" "42.0.2"
+    "@ckeditor/ckeditor5-show-blocks" "42.0.2"
+    "@ckeditor/ckeditor5-source-editing" "42.0.2"
+    "@ckeditor/ckeditor5-special-characters" "42.0.2"
+    "@ckeditor/ckeditor5-style" "42.0.2"
+    "@ckeditor/ckeditor5-table" "42.0.2"
+    "@ckeditor/ckeditor5-theme-lark" "42.0.2"
+    "@ckeditor/ckeditor5-typing" "42.0.2"
+    "@ckeditor/ckeditor5-ui" "42.0.2"
+    "@ckeditor/ckeditor5-undo" "42.0.2"
+    "@ckeditor/ckeditor5-upload" "42.0.2"
+    "@ckeditor/ckeditor5-utils" "42.0.2"
+    "@ckeditor/ckeditor5-watchdog" "42.0.2"
+    "@ckeditor/ckeditor5-widget" "42.0.2"
+    "@ckeditor/ckeditor5-word-count" "42.0.2"
+
+color-convert@2.0.1:
+  version "2.0.1"
+  resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz"
+  integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+  dependencies:
+    color-name "~1.1.4"
+
+color-name@^1.0.0, color-name@~1.1.4:
+  version "1.1.4"
+  resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
+  integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+color-parse@1.4.2:
+  version "1.4.2"
+  resolved "https://registry.npmjs.org/color-parse/-/color-parse-1.4.2.tgz"
+  integrity sha512-RI7s49/8yqDj3fECFZjUI1Yi0z/Gq1py43oNJivAIIDSyJiOZLfYCRQEgn8HEVAj++PcRe8AnL2XF0fRJ3BTnA==
+  dependencies:
+    color-name "^1.0.0"
+
+lodash-es@4.17.21:
+  version "4.17.21"
+  resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz"
+  integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
+
+marked@4.0.12:
+  version "4.0.12"
+  resolved "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz"
+  integrity sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==
+
+turndown-plugin-gfm@1.0.2:
+  version "1.0.2"
+  resolved "https://registry.npmjs.org/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.2.tgz"
+  integrity sha512-vwz9tfvF7XN/jE0dGoBei3FXWuvll78ohzCZQuOb+ZjWrs3a0XhQVomJEb2Qh4VHTPNRO4GPZh0V7VRbiWwkRg==
+
+turndown@7.2.0:
+  version "7.2.0"
+  resolved "https://registry.npmjs.org/turndown/-/turndown-7.2.0.tgz"
+  integrity sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==
+  dependencies:
+    "@mixmark-io/domino" "^2.2.0"
+
+vanilla-colorful@0.7.2:
+  version "0.7.2"
+  resolved "https://registry.npmjs.org/vanilla-colorful/-/vanilla-colorful-0.7.2.tgz"
+  integrity sha512-z2YZusTFC6KnLERx1cgoIRX2CjPRP0W75N+3CC6gbvdX5Ch47rZkEMGO2Xnf+IEmi3RiFLxS18gayMA27iU7Kg==
-- 
GitLab


From 8ae34a0438d08988c4bbe3912d24d8d1bc21c8dd Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Fri, 23 Aug 2024 08:47:07 -0700
Subject: [PATCH 02/33] Widgets, page elements, and inline editor in Layout
 Builder.

---
 edit_plus.module                              | 17 +---
 js/edit_plus/editable-element.js              | 10 +-
 js/edit_plus/entity-form.js                   |  9 +-
 js/edit_plus/fields/inline-editor.js          | 96 ++++++++++---------
 js/edit_plus/utilities.js                     | 14 ++-
 src/EventSubscriber/AttributesTrait.php       | 23 +++++
 src/EventSubscriber/CloneFieldAttribute.php   |  5 +-
 .../DefaultFieldAttributes.php                |  4 +-
 .../InlineEditorFieldAttributes.php           |  7 +-
 src/EventSubscriber/MediaFieldAttributes.php  |  7 +-
 10 files changed, 111 insertions(+), 81 deletions(-)
 create mode 100644 src/EventSubscriber/AttributesTrait.php

diff --git a/edit_plus.module b/edit_plus.module
index bc88e93..7e77d58 100644
--- a/edit_plus.module
+++ b/edit_plus.module
@@ -73,29 +73,14 @@ function edit_plus_preprocess_field(&$variables) {
 
   $variables['attributes']['data-edit-plus-field-value-wrapper'] = sprintf('%s::%s::%s::%s', $entity->getEntityTypeId(), $id, $element['#field_name'], $main_property);
 
-  // Consult the form used to control this display.
-//  static $forms;
-//  if (empty($forms)) {
-//    $forms = [];
-//  }
-//  $key = $entity->getEntityTypeId() . '::' . $entity->id();
-//  if (empty($forms[$key])) {
-//    $form = Drupal::classResolver()->getInstanceFromDefinition(MultipleEntityFormController::class)->entityForm(Drupal::requestStack()->getCurrentRequest(), $entity->getEntityTypeId(), $entity);
-//    $forms[$key] = $form;
-//  } else {
-//    $form = $forms[$key];
-//  }
-
   foreach ($variables['items'] as $delta => &$item) {
-//    $type = edit_plus_find_widget_type($form['form'][$element['#field_name']], $definition);
     $item['content'] = [
       'edit_plus_wrapper' => [
         '#type' => 'container',
         '#attributes' => [
           'class' => ['edit-plus-field-value'],
           'data-edit-plus-id' => sprintf('%s::%s::%s::%s::%s::%s::%s::%s::%s', $entity->getEntityTypeId(), $id, $element['#field_name'], $delta, $element['#language'], $view_mode, $element['#field_type'], $element['#formatter'], $main_property),
-//          'data-edit-plus-id' => sprintf('%s::%s::%s::%s::%s::%s::%s::%s::%s', $entity->getEntityTypeId(), $id, $element['#field_name'], $delta, $element['#language'], $view_mode, $element['#field_type'], $type, $main_property),
-          'data-edit-plus-markup-item-id' => sprintf('%s::%s::%s::%s::%s', $entity->getEntityTypeId(), $id, $element['#field_name'], $delta, $main_property),
+          'data-edit-plus-page-element-id' => sprintf('%s::%s::%s::%s::%s', $entity->getEntityTypeId(), $id, $element['#field_name'], $delta, $main_property),
         ],
         'content' => $item['content'],
         '#cache' => [
diff --git a/js/edit_plus/editable-element.js b/js/edit_plus/editable-element.js
index fe0a8b1..8f768f3 100644
--- a/js/edit_plus/editable-element.js
+++ b/js/edit_plus/editable-element.js
@@ -153,14 +153,8 @@ export class EditableElement {
    *   within a form item wrapper.
    */
   static createFromFormItem(element) {
-    let editableElement;
-    const wrapper = element.closest('.edit-plus-form-item-wrapper');
-    if (wrapper) {
-      editableElement = new EditableElement(wrapper.dataset.editPlusPageElementId);
-    } else {
-      const pageElement = document.querySelector('[data-edit-plus-markup-item-id="' + element.dataset.editPlusFormItemId + '"]');
-      editableElement = new EditableElement(pageElement.dataset.editPlusId);
-    }
+    const pageElement = util.getPageElement(element);
+    const editableElement = new EditableElement(pageElement.dataset.editPlusId);
     editableElement.setWidget();
     return editableElement;
   }
diff --git a/js/edit_plus/entity-form.js b/js/edit_plus/entity-form.js
index b2aa589..b644457 100644
--- a/js/edit_plus/entity-form.js
+++ b/js/edit_plus/entity-form.js
@@ -14,6 +14,7 @@ export const getForm = (EditableElement) => {
   // Hide/cache previously loaded forms.
   document.querySelectorAll('.edit-plus-form').forEach(form => {
     form.classList.add('toolbar-plus-hidden');
+    form.removeAttribute('data-offset-right');
   });
   // Return the requested form if we already have it.
   const formExists = EditableElement.getForm();
@@ -71,7 +72,10 @@ const getLayoutBuilderEntityForm = (EditableElement) => {
     for (let i = storageIds.length - 2; i >= 0; i--) {
       const layoutBlock = storageIds[i].closest('[data-layout-builder-layout-block]');
       const section = layoutBlock.closest('[data-layout-builder-section-delta]');
-      nestedStoragePath = `${section.dataset.layoutBuilderSectionDelta}&${layoutBlock.dataset.layoutBuilderBlockUuid}` + nestedStoragePath;
+      if (nestedStoragePath) {
+        nestedStoragePath += '&';
+      }
+      nestedStoragePath += `${section.dataset.layoutBuilderSectionDelta}&${layoutBlock.dataset.layoutBuilderBlockUuid}`;
     }
     nestedStoragePath = nestedStoragePath ? '/' + nestedStoragePath : nestedStoragePath;
     let url = Drupal.url(`edit-plus/update/block/${storageType}/${storageId}/${sectionDelta}/${region}/${blockUuid}${nestedStoragePath}`);
@@ -104,9 +108,6 @@ const getLayoutBuilderEntityForm = (EditableElement) => {
             Drupal.Ajax.prototype.success.call(ajax, response, status).then(() => {
               resolve({status: 'new_form'});
             });
-          })
-          .then(() => {
-            jQuery('#toolbar-plus-sidebar').show();
           });
       }
     });
diff --git a/js/edit_plus/fields/inline-editor.js b/js/edit_plus/fields/inline-editor.js
index 2555388..f35c561 100644
--- a/js/edit_plus/fields/inline-editor.js
+++ b/js/edit_plus/fields/inline-editor.js
@@ -19,6 +19,7 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
      */
     supportedWidgets = [
       'text_textarea',
+      'text_textarea_with_summary',
     ];
 
     /**
@@ -174,17 +175,20 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
             if (ckeditor5Id) {
               let destroyPromise = Drupal.behaviors.EditPlusInlineEditors.detachEditor(e.currentTarget, inlineEditElement.dataset.ckeditor5Id);
               destroyPromise.then(() => {
-                Drupal.behaviors.EditPlusInlineEditors.showInputElement(markupElement, formatSelector.value);
-                Drupal.EditPlus.FieldPluginManager.getPlugin(EditableElement).focus(EditableElement);
+                Drupal.behaviors.EditPlusInlineEditors.attachEditorWithNewFormat(EditableElement, markupElement, formatSelector.value);
               });
             } else {
-              Drupal.behaviors.EditPlusInlineEditors.showInputElement(markupElement, formatSelector.value);
-              Drupal.EditPlus.FieldPluginManager.getPlugin(EditableElement).focus(EditableElement);
+              Drupal.behaviors.EditPlusInlineEditors.attachEditorWithNewFormat(EditableElement, markupElement, formatSelector.value);
             }
           }
         });
       });
     },
+    attachEditorWithNewFormat: (EditableElement, markupElement, format) => {
+      once.remove('EditPlusAttachEditor', markupElement);
+      Drupal.behaviors.EditPlusInlineEditors.showInputElement(markupElement, format);
+      Drupal.EditPlus.FieldPluginManager.getPlugin(EditableElement).focus(EditableElement);
+    },
 
     /**
      * Show input element.
@@ -221,54 +225,56 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
      *   The field formatter ID.
      */
     attachEditor: (element, format) => {
-      // Hide the textarea if it hasn't been already.
-      element.classList.remove('edit-plus-hidden');
-      element.closest('.edit-plus-form-item').querySelector('textarea').classList.add('edit-plus-hidden');
+      once('EditPlusAttachEditor', element).forEach(element => {
+        // Hide the textarea if it hasn't been already.
+        element.classList.remove('edit-plus-hidden');
+        element.closest('.edit-plus-form-item').querySelector('textarea').classList.add('edit-plus-hidden');
 
-      // Process the field formatter config.
-      const { editorInline } = CKEditor5;
-      const {
-        toolbar,
-        plugins,
-        config: pluginConfig,
-        language,
-      } = format.editorSettings;
-      const extraPlugins = core.selectPlugins(plugins);
-      const config = {
-        extraPlugins,
-        toolbar,
-        language,
-        ...core.processConfig(pluginConfig),
-      };
+        // Process the field formatter config.
+        const { editorInline } = CKEditor5;
+        const {
+          toolbar,
+          plugins,
+          config: pluginConfig,
+          language,
+        } = format.editorSettings;
+        const extraPlugins = core.selectPlugins(plugins);
+        const config = {
+          extraPlugins,
+          toolbar,
+          language,
+          ...core.processConfig(pluginConfig),
+        };
 
-      // Add an Inline Editor
-      const id = core.setElementId(element);
-      const { InlineEditor } = editorInline;
+        // Add an Inline Editor
+        const id = core.setElementId(element);
+        const { InlineEditor } = editorInline;
 
-      InlineEditor
-        .create(element, config)
-        .then((editor) => {
-          Drupal.EditPlus.Ckeditor5Instances.set(id, editor);
-          const formItem = editor.sourceElement.closest('.edit-plus-form-item');
+        InlineEditor
+          .create(element, config)
+          .then((editor) => {
+            Drupal.EditPlus.Ckeditor5Instances.set(id, editor);
+            const formItem = editor.sourceElement.closest('.edit-plus-form-item');
 
 
-          // Does this editor need focus right away? If the CKEditor was the
-          // first thing that was clicked that loaded the form, we should focus
-          // the editor as soon as it's created.
-          if (id === Drupal.EditPlus.FocusInlineEditor) {
-            Drupal.EditPlus.FocusInlineEditor = null;
-            editor.focus();
+            // Does this editor need focus right away? If the CKEditor was the
+            // first thing that was clicked that loaded the form, we should focus
+            // the editor as soon as it's created.
+            if (id === Drupal.EditPlus.FocusInlineEditor) {
+              Drupal.EditPlus.FocusInlineEditor = null;
+              editor.focus();
 
-            // Remember the editors original state.
-            const EditableElement = editableElement.EditableElement.createFromFormItem(formItem);
-            const plugin = Drupal.EditPlus.FieldPluginManager.getPlugin(EditableElement);
-            plugin.originalData.set(EditableElement.info.elementId, plugin.getInputValue(formItem));
+              // Remember the editors original state.
+              const EditableElement = editableElement.EditableElement.createFromFormItem(formItem);
+              const plugin = Drupal.EditPlus.FieldPluginManager.getPlugin(EditableElement);
+              plugin.originalData.set(EditableElement.info.elementId, plugin.getInputValue(formItem));
 
-          }
-        })
-        .catch(err => {
-          console.error(err.stack);
-        });
+            }
+          })
+          .catch(err => {
+            console.error(err.stack);
+          });
+      });
     },
 
     /**
diff --git a/js/edit_plus/utilities.js b/js/edit_plus/utilities.js
index 410c701..3216e69 100644
--- a/js/edit_plus/utilities.js
+++ b/js/edit_plus/utilities.js
@@ -116,9 +116,21 @@ export const getMarkupItem = (formItem) => {
     return null;
   }
 
-  return document.querySelector('[data-edit-plus-markup-item-id="' + formItem.dataset.editPlusFormItemId + '"]');
+  return document.querySelector('[data-edit-plus-page-element-id="' + formItem.dataset.editPlusFormItemId + '"]');
 }
 
+export const getPageElement = (element) => {
+  // Most elements.
+  let formItem = element.closest('.edit-plus-form-item');
+  // Some parts of Media Library widget.
+  if (!formItem) {
+    formItem = element.querySelector('.edit-plus-form-item');
+  }
+
+  return document.querySelector('[data-edit-plus-page-element-id="' + formItem.dataset.editPlusFormItemId + '"]');
+}
+
+
 /**
  * Get Form ID.
  *
diff --git a/src/EventSubscriber/AttributesTrait.php b/src/EventSubscriber/AttributesTrait.php
new file mode 100644
index 0000000..785fd71
--- /dev/null
+++ b/src/EventSubscriber/AttributesTrait.php
@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\edit_plus\EventSubscriber;
+
+use Drupal\edit_plus\Event\FieldAttributes;
+
+trait AttributesTrait {
+
+  protected static function getWidget(FieldAttributes $event): ?string {
+    $field_name = $event->getFieldName();
+    $form_display = $event->getFormState()->get('form_display');
+    if (empty($form_display))  {
+      // Must not be an entity form, load the form display.
+      $entity = $event->getEntity();
+      $form_display = \Drupal::service('entity_display.repository')->getFormDisplay($entity->getEntityTypeId(), $entity->bundle());
+    }
+
+    return $form_display->getComponent($field_name)['type'];
+  }
+
+}
diff --git a/src/EventSubscriber/CloneFieldAttribute.php b/src/EventSubscriber/CloneFieldAttribute.php
index a8d3973..f79775b 100644
--- a/src/EventSubscriber/CloneFieldAttribute.php
+++ b/src/EventSubscriber/CloneFieldAttribute.php
@@ -13,16 +13,19 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  */
 class CloneFieldAttribute implements EventSubscriberInterface {
 
+  use AttributesTrait;
+
   const DO_NOT_CLONE = [
     'entity_reference_autocomplete_tags',
     'text_textarea',
+    'text_textarea_with_summary',
   ];
 
   public function addFormItemAttributesAlter(FieldAttributes $event) {
     $field_name = $event->getFieldName();
     $form = $event->getForm();
     $form_item = &$form[$field_name];
-    $widget = $event->getFormState()->get('form_display')->getComponent($field_name)['type'];
+    $widget = self::getWidget($event);
 
     if (empty($form_item['#attributes']['data-edit-plus-clone']) && $widget) {
       $field_definition = $event->getEntity()->getFieldDefinition($field_name);
diff --git a/src/EventSubscriber/DefaultFieldAttributes.php b/src/EventSubscriber/DefaultFieldAttributes.php
index 35853e9..7b2881d 100644
--- a/src/EventSubscriber/DefaultFieldAttributes.php
+++ b/src/EventSubscriber/DefaultFieldAttributes.php
@@ -16,6 +16,8 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  */
 class DefaultFieldAttributes implements EventSubscriberInterface {
 
+  use AttributesTrait;
+
   /**
    * Add form item attributes.
    *
@@ -31,7 +33,7 @@ class DefaultFieldAttributes implements EventSubscriberInterface {
     $form_item = &$form[$field_name];
     $entity = $event->getEntity();
     $form_item['#attributes']['data-edit-plus-form-item-wrapper-id'] = sprintf('%s::%s::%s::%s', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity), $field_name, 'value');
-    $form_item['#attributes']['data-edit-plus-form-item-widget'] = $event->getFormState()->get('form_display')->getComponent($field_name)['type'];
+    $form_item['#attributes']['data-edit-plus-form-item-widget'] = self::getWidget($event);
     $form_item['#attributes']['class'][] = 'edit-plus-form-item-wrapper';
     $form_item['#attributes']['class'][] = 'edit-plus-hidden';
 
diff --git a/src/EventSubscriber/InlineEditorFieldAttributes.php b/src/EventSubscriber/InlineEditorFieldAttributes.php
index 64f1fc6..643f73a 100644
--- a/src/EventSubscriber/InlineEditorFieldAttributes.php
+++ b/src/EventSubscriber/InlineEditorFieldAttributes.php
@@ -13,8 +13,11 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  */
 class InlineEditorFieldAttributes implements EventSubscriberInterface {
 
+  use AttributesTrait;
+
   const INLINE_EDITOR_WIDGET_MAPPING = [
-    'text_textarea'
+    'text_textarea',
+    'text_textarea_with_summary',
   ];
 
   /**
@@ -30,7 +33,7 @@ class InlineEditorFieldAttributes implements EventSubscriberInterface {
     $field_name = $event->getFieldName();
     $form = $event->getForm();
     $form_item = &$form[$field_name];
-    $widget = $event->getFormState()->get('form_display')->getComponent($field_name)['type'];
+    $widget = self::getWidget($event);
 
     if (in_array($widget, static::INLINE_EDITOR_WIDGET_MAPPING)) {
       foreach (Element::children($form_item['widget']) as $delta) {
diff --git a/src/EventSubscriber/MediaFieldAttributes.php b/src/EventSubscriber/MediaFieldAttributes.php
index 4f44ba6..e42b129 100644
--- a/src/EventSubscriber/MediaFieldAttributes.php
+++ b/src/EventSubscriber/MediaFieldAttributes.php
@@ -12,6 +12,8 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  */
 class MediaFieldAttributes implements EventSubscriberInterface {
 
+  use AttributesTrait;
+
   /**
    * Add form item attributes.
    *
@@ -33,7 +35,7 @@ class MediaFieldAttributes implements EventSubscriberInterface {
       $form_item['#attributes']['data-edit-plus-handle'] = 'wrapper';
       $form_item['#attributes']['data-edit-plus-clone'] = 'true';
       $form_item['#attributes']['data-edit-plus-form-item-wrapper-id'] = sprintf('%s::%s::%s::%s', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity), $field_name, 'value');
-      $form_item['#attributes']['data-edit-plus-form-item-widget'] = $event->getFormState()->get('form_display')->getComponent($field_name)['type'];
+      $form_item['#attributes']['data-edit-plus-form-item-widget'] = self::getWidget($event);
       $form_item['widget']['#type'] = 'container';
       $form_item['widget']['#attributes']['class'][] = 'edit-plus-form-item';
       $form_item['widget']['#attributes']['data-edit-plus-form-item-id'] = sprintf('%s::%s::%s::%s::%s', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity), $field_name, 0, 'value');
@@ -59,8 +61,7 @@ class MediaFieldAttributes implements EventSubscriberInterface {
    *   Whether the field is a Media field.
    */
   public static function isMediaReferenceField(FieldAttributes $event): bool {
-    $widget = $event->getFormState()->get('form_display')->getComponent($event->getFieldName())['type'];
-    return $widget === 'media_library_widget';
+    return self::getWidget($event) === 'media_library_widget';
   }
 
   /**
-- 
GitLab


From f5a592ef6023683e941f53b0714f60d38f11fd5a Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Mon, 26 Aug 2024 12:33:03 -0700
Subject: [PATCH 03/33] Tweak page element > form item markup relationship.

---
 js/edit_plus/fields/field-plugin-base.js |  2 +-
 js/edit_plus/utilities.js                | 15 +++++++++++----
 src/EditPlusFormTrait.php                |  4 +---
 3 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/js/edit_plus/fields/field-plugin-base.js b/js/edit_plus/fields/field-plugin-base.js
index 08d118a..eb9f890 100644
--- a/js/edit_plus/fields/field-plugin-base.js
+++ b/js/edit_plus/fields/field-plugin-base.js
@@ -304,7 +304,7 @@ export class FieldPluginBase {
     clone.dataset.editPlusClone = formElementHandle.dataset.editPlusFormItemWrapperId;
 
     // Pass along the Edit+ ID so recreate EditableElement as changes occur
-    formElementHandle.dataset.editPlusPageElementId = EditableElement.getPageElement().dataset.editPlusId;
+    formElementHandle.dataset.editPlusPageElementEditPlusId = EditableElement.getPageElement().dataset.editPlusId;
 
     // Watch for changes to the original element.
     this.observer = new MutationObserver((mutations) => {
diff --git a/js/edit_plus/utilities.js b/js/edit_plus/utilities.js
index 3216e69..45f97b0 100644
--- a/js/edit_plus/utilities.js
+++ b/js/edit_plus/utilities.js
@@ -120,12 +120,19 @@ export const getMarkupItem = (formItem) => {
 }
 
 export const getPageElement = (element) => {
-  // Most elements.
+  const wrapper = element.closest('[data-edit-plus-page-element-edit-plus-id]')
+  if (wrapper) {
+    return document.querySelector('[data-edit-plus-id="' + wrapper.dataset.editPlusPageElementEditPlusId + '"]')
+  }
+
+  // Inline Editor
   let formItem = element.closest('.edit-plus-form-item');
+
+  // @todo This is a candidate for removal. I think this is covered by data-edit-plus-page-element-edit-plus-id now.
   // Some parts of Media Library widget.
-  if (!formItem) {
-    formItem = element.querySelector('.edit-plus-form-item');
-  }
+  // if (!formItem) {
+  //   formItem = element.querySelector('.edit-plus-form-item');
+  // }
 
   return document.querySelector('[data-edit-plus-page-element-id="' + formItem.dataset.editPlusFormItemId + '"]');
 }
diff --git a/src/EditPlusFormTrait.php b/src/EditPlusFormTrait.php
index 09c79d1..e4e5661 100644
--- a/src/EditPlusFormTrait.php
+++ b/src/EditPlusFormTrait.php
@@ -22,8 +22,6 @@ use Drupal\field_sample_value\SampleValueEntityGeneratorInterface;
 
 trait EditPlusFormTrait {
 
-  public $editPlusTempStore;
-
   public function prepareFormForInlineEditing(&$form, FormStateInterface $form_state) {
     $entity = $this->getFormEntity($form, $form_state);
     $entity = $this->editPlusTempstoreRepository->get($entity);
@@ -113,7 +111,7 @@ trait EditPlusFormTrait {
    * Generate field values before adding an empty field to the page.
    */
   public function populateEmptyField(&$form, FormStateInterface $form_state) {
-    $entity = $this->editPlusTempStore->get($this->getFormEntity($form, $form_state));
+    $entity = $this->editPlusTempstoreRepository->get($this->getFormEntity($form, $form_state));
     $input = $form_state->getUserInput();
     [$_, $field_name] = explode('::', $input['_triggering_element_name']);
     $field = $entity->get($field_name);
-- 
GitLab


From 2b36f8c3f4a5ec91cec271c0b6ccc0354b475af1 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Fri, 30 Aug 2024 08:49:21 -0700
Subject: [PATCH 04/33] Tweaks.

---
 edit_plus.libraries.yml   | 2 +-
 js/edit_plus/utilities.js | 2 +-
 src/Ui.php                | 1 +
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/edit_plus.libraries.yml b/edit_plus.libraries.yml
index 719a71d..537ee1e 100644
--- a/edit_plus.libraries.yml
+++ b/edit_plus.libraries.yml
@@ -18,7 +18,7 @@ library:
     - core/ckeditor5.autoformat
     - core/ckeditor5.htmlSupport
     - core/ckeditor5.sourceEditing
-    - core/ckeditor5.pasteFromOffice'
+    - core/ckeditor5.pasteFromOffice
     - ckeditor5/internal.drupal.ckeditor5
     - ckeditor5/internal.drupal.ckeditor5.emphasis
     - ckeditor5/internal.drupal.ckeditor5.htmlEngine
diff --git a/js/edit_plus/utilities.js b/js/edit_plus/utilities.js
index 45f97b0..20db3a0 100644
--- a/js/edit_plus/utilities.js
+++ b/js/edit_plus/utilities.js
@@ -122,7 +122,7 @@ export const getMarkupItem = (formItem) => {
 export const getPageElement = (element) => {
   const wrapper = element.closest('[data-edit-plus-page-element-edit-plus-id]')
   if (wrapper) {
-    return document.querySelector('[data-edit-plus-id="' + wrapper.dataset.editPlusPageElementEditPlusId + '"]')
+    return document.querySelector('[data-edit-plus-id="' + wrapper.dataset.editPlusPageElementEditPlusId + '"]');
   }
 
   // Inline Editor
diff --git a/src/Ui.php b/src/Ui.php
index 31e39e7..6edd929 100644
--- a/src/Ui.php
+++ b/src/Ui.php
@@ -7,6 +7,7 @@ use Drupal\Core\Url;
 class Ui {
 
   function buildBottomBar($actively_used_tempstore_entities, $destination) {
+    // @todo deprecated, remove.
     return [
       'toolbar_plus' => [
         '#type' => 'container',
-- 
GitLab


From 8a8a5dd95b17d0c61b1b62689c9a3c50372a0fdd Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Wed, 4 Sep 2024 11:02:41 -0700
Subject: [PATCH 05/33] Use view_mode from display when loading tempstore
 entities.

---
 .../src/EditPlusLbTempstoreRepository.php     | 26 ++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/modules/edit_plus_lb/src/EditPlusLbTempstoreRepository.php b/modules/edit_plus_lb/src/EditPlusLbTempstoreRepository.php
index 9409c3a..34e5101 100644
--- a/modules/edit_plus_lb/src/EditPlusLbTempstoreRepository.php
+++ b/modules/edit_plus_lb/src/EditPlusLbTempstoreRepository.php
@@ -4,13 +4,17 @@ namespace Drupal\edit_plus_lb;
 
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Plugin\Context\Context;
+use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Plugin\Context\EntityContext;
 use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Entity\Entity\EntityViewDisplay;
+use Drupal\Core\Entity\FieldableEntityInterface;
 use Drupal\Core\TempStore\SharedTempStoreFactory;
 use Drupal\Core\Plugin\Context\ContextDefinition;
 use Drupal\layout_builder\SectionStorageInterface;
 use Drupal\layout_builder\LayoutEntityHelperTrait;
 use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
+use Drupal\layout_builder\Entity\LayoutEntityDisplayInterface;
 use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay;
 use Drupal\layout_builder\Plugin\SectionStorage\DefaultsSectionStorage;
 use Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface;
@@ -96,7 +100,26 @@ class EditPlusLbTempstoreRepository extends EditPlusTempstoreRepositoryBase {
    *   The section storage for the entity.
    */
   private function getSectionStorageForEntity(EntityInterface $entity): ?SectionStorageInterface {
-    $section_storage = $this->lbGetSectionStorageForEntity($entity);
+    // This is a copy and tweak of LayoutEntityHelperTrait. It finds the
+    // section storage by context.
+    $view_mode = 'full';
+    if ($entity instanceof LayoutEntityDisplayInterface) {
+      $contexts['display'] = EntityContext::fromEntity($entity);
+      $contexts['view_mode'] = new Context(new ContextDefinition('string'), $entity->getMode());
+    }
+    else {
+      $contexts['entity'] = EntityContext::fromEntity($entity);
+      if ($entity instanceof FieldableEntityInterface) {
+        $display = EntityViewDisplay::collectRenderDisplay($entity, $view_mode);
+        if ($display instanceof LayoutEntityDisplayInterface) {
+          $contexts['display'] = EntityContext::fromEntity($display);
+        }
+        // Fall back to the actually used view mode (e.g. full > default).
+        $contexts['view_mode'] = new Context(new ContextDefinition('string'), $display->getMode());
+      }
+    }
+    $section_storage = $this->sectionStorageManager->findByContext($contexts, new CacheableMetadata());
+    // Create an override section storage if we have a default section storage.
     if ($section_storage instanceof DefaultsSectionStorage) {
       $view_mode = 'full';
       $contexts['entity'] = EntityContext::fromEntity($entity);
@@ -107,6 +130,7 @@ class EditPlusLbTempstoreRepository extends EditPlusTempstoreRepositoryBase {
       if (empty($override_section_storage)) {
         return NULL;
       }
+      // Copy the sections from the default to the override.
       $sections = $section_storage->getSections();
       if (!empty($sections)) {
         foreach ($sections as $section) {
-- 
GitLab


From ec7536838e1c0e94b2b191f2734701741212ebd8 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Wed, 4 Sep 2024 12:14:32 -0700
Subject: [PATCH 06/33] get view mode with fallback.

---
 edit_plus.module | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/edit_plus.module b/edit_plus.module
index 7e77d58..b4f26d2 100644
--- a/edit_plus.module
+++ b/edit_plus.module
@@ -56,7 +56,7 @@ function edit_plus_preprocess_field(&$variables) {
   // always names the "_custom" view mode).
   // @see \Drupal\Core\Field\FieldItemListInterface::view()
   // @see https://www.drupal.org/node/2120335
-  $view_mode = $element['#view_mode'];
+  $view_mode = _edit_plus_get_view_mode($entity, $element['#view_mode']);
   if ($view_mode === '_custom') {
     // Support layout builder field blocks.
     if (!empty($element['#third_party_settings']['layout_builder']['view_mode'])) {
@@ -217,4 +217,38 @@ function edit_plus_form_field_config_edit_form_alter(&$form, FormStateInterface
   \Drupal::service('edit_plus.field_config_form_alter')->formAlter($form, $form_state);
 }
 
+/**
+ * Edit plus get view mode.
+ *
+ * Falls back to a view mode that exists for this entity.
+ * @todo this needs to be consolidated with the other view mode handling.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ *   The entity.
+ * @param string|NULL $view_mode
+ *   The perspective view mode.
+ *
+ * @return string
+ *   The view mode.
+ *
+ * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
+ * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
+ */
+function _edit_plus_get_view_mode(EntityInterface $entity, string $view_mode = NULL): string {
+  static $cached_view_modes;
+  $original_id = $entity->getEntityTypeId() . "." . $entity->bundle() . "." . $view_mode;
+
+  if (!empty($cached_view_modes[$original_id])) {
+    return $cached_view_modes[$original_id];
+  }
+
+  $storage = \Drupal::entityTypeManager()->getStorage('entity_view_display');
+  $view_display = $storage->load($original_id);
+  if (empty($view_display)) {
+    $default_id = $entity->getEntityTypeId() . "." . $entity->bundle() . ".default";
+    $view_display = $storage->load($default_id);
+  }
+  $cached_view_modes[$original_id] = $view_display->getMode();
+  return $cached_view_modes[$original_id];
+}
 
-- 
GitLab


From 40ce87c64a1463d48a98d72e0dd4ef58ddf9e9af Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Fri, 6 Sep 2024 09:05:57 -0700
Subject: [PATCH 07/33] Autosave sidebar and handle view mode changes.

---
 edit_plus.module                              | 28 ++++-------
 js/edit-plus.js                               |  4 --
 js/edit_plus/entity-form.js                   | 47 +++++++++++--------
 .../edit_plus_lb/src/Form/UpdateBlockForm.php | 33 +++++--------
 src/EditPlusFormTrait.php                     | 41 +++++++++++++---
 src/EventSubscriber/HandleFieldAttribute.php  |  5 ++
 src/Form/InlineEntityFormAlter.php            |  2 +-
 7 files changed, 87 insertions(+), 73 deletions(-)

diff --git a/edit_plus.module b/edit_plus.module
index b4f26d2..64daabc 100644
--- a/edit_plus.module
+++ b/edit_plus.module
@@ -23,6 +23,7 @@ function edit_plus_page_attachments(array &$attachments) {
   if (\Drupal::service('router.admin_context')->isAdminRoute($route)) {
     return;
   }
+  // Make the filter formats available on editable pages (currently all non-admin pages).
   $attachments['#cache']['contexts'][] = 'user.permissions';
   $formats = Drupal::service('entity_type.manager')->getStorage('filter_format')->loadMultiple();
   $editor_attachments = \Drupal::service('plugin.manager.editor')->getAttachments(array_keys($formats));
@@ -91,6 +92,13 @@ function edit_plus_preprocess_field(&$variables) {
   }
 }
 
+/**
+ * Implements hook_preprocess_HOOK().
+ */
+function edit_plus_preprocess_block(&$variables) {
+  $break_point = TRUE; // @todo Remove!
+}
+
 function getCacheTag($entity) {
   return sprintf('edit_plus:%s.%s', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity));
 }
@@ -148,26 +156,6 @@ function template_preprocess_inline_textarea(&$variables) {
   $variables['inline_editor_attributes'] =  new Attribute(['class' => ['edit-plus-inline-edit']]);
 }
 
-// @todo This should tie into toolbar +.
-function buildBottomBar(array &$page_bottom) {
-  $actively_used_tempstore_entities = edit_plus_active_tempstore_entities();
-  if (!empty($actively_used_tempstore_entities)) {
-    // Only build the bottom bar if we are on the canonical page of the tempstore
-    // entity.
-    $route = \Drupal::service('current_route_match');
-    foreach ($actively_used_tempstore_entities as $tempstore_entity) {
-      $route_entity = $route->getParameter($tempstore_entity->getEntityTypeId());
-      if (empty($route_entity) || (!empty($route_entity) && $route_entity->id() !== $tempstore_entity->id())) {
-        continue;
-      }
-      $canonical_route_name = $route_entity->toUrl('canonical')->getRouteName();
-      if ($route->getRouteName() === $canonical_route_name) {
-        $page_bottom['bottom_bar']['edit_plus_bottom_bar'] = Drupal::service('edit_plus.ui')->buildBottomBar($actively_used_tempstore_entities, \Drupal::destination()->get());
-      }
-    }
-  }
-}
-
 /**
  * Active tempstore entities.
  *
diff --git a/js/edit-plus.js b/js/edit-plus.js
index 38bdefe..dee8c04 100644
--- a/js/edit-plus.js
+++ b/js/edit-plus.js
@@ -57,10 +57,6 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
     entityForm.getForm(EditableElement).then((response, status) => {
       EditableElement.setWidget();
       Drupal.EditPlus.FieldPluginManager.getPlugin(EditableElement).edit(EditableElement);
-
-      // if (response.status === 'new_form') {
-      //   entityForm.autosaveNonEditableElements(EditableElement);
-      // }
     });
   }
 
diff --git a/js/edit_plus/entity-form.js b/js/edit_plus/entity-form.js
index b644457..1a9eda7 100644
--- a/js/edit_plus/entity-form.js
+++ b/js/edit_plus/entity-form.js
@@ -154,22 +154,7 @@ const getEntityForm = (EditableElement) => {
     EditableElement.info.ajaxReturnForm = false;
   });
 }
-// @todo I think we need to tag auto save items in the sidebar on the backend.
-// export const autosaveNonEditableElements = (EditableElement) => {
-//   EditableElement.getForm().querySelectorAll('[data-edit-plus-input]').forEach(input => {
-//     const formItem = input.closest('[data-edit-plus-form-item-id]');
-//     if (formItem) {
-//       const pageElement = utilities.getMarkupItem(formItem);
-//       if (!pageElement) {
-//         // Auto save changes to sidebar form items.
-//         input.addEventListener('change', e => {
-//           const updateButton = input.closest('form').querySelector('.edit-plus-update-button');
-//           jQuery(updateButton).mousedown();
-//         });
-//       }
-//     }
-//   });
-// }
+
 
 /**
  * Flag that the page is currently being updated.
@@ -186,12 +171,17 @@ export let editPlusIsUpdating = false;
  * @param isEmpty
  *   Whether the field has been emptied or not. Emptied fields are moved to the
  *   sidebar.
+ * @param form
+ *   Pass the form element directly when an EditableElement isn't available,
+ *   but you still need to submit the form like when a sidebar form item changes.
  */
-export const updateTempstore = (EditableElement, isEmpty) => {
-  const form = EditableElement.getFormItemWrapper().closest('form');
+export const updateTempstore = (EditableElement, isEmpty, form = null) => {
+  if (!form) {
+    form = EditableElement.getFormItemWrapper().closest('form');
+  }
 
   // Move emptied fields to the sidebar.
-  if (isEmpty) {
+  if (EditableElement && isEmpty) {
     form.querySelector('#empty-field').value = EditableElement.info.fieldName;
   }
 
@@ -204,3 +194,22 @@ export const updateTempstore = (EditableElement, isEmpty) => {
 jQuery.fn.editPlusIsDoneUpdating = () => {
   editPlusIsUpdating = false;
 }
+
+(($, Drupal, once) => {
+
+  /**
+   * Edit+ entity form auto save.
+   *
+   * Auto saves form items in the sidebar when the user changes its value.
+   */
+  Drupal.behaviors.EditPlusEntityFormAutoSave = {
+    attach: (context, settings) => {
+      once('EditPlusEntityFormAutoSave', '[data-edit-plus-auto-submit]', context).forEach(formItem => {
+        formItem.addEventListener('change', e => {
+          updateTempstore(null, false, e.target.closest('form'));
+        });
+      });
+    }
+  };
+})(jQuery, Drupal, once);
+
diff --git a/modules/edit_plus_lb/src/Form/UpdateBlockForm.php b/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
index 1ec5e65..5c69677 100644
--- a/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
+++ b/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
@@ -87,6 +87,15 @@ class UpdateBlockForm extends UpdateBlockFormBase implements EntityFormInterface
     $form = parent::buildForm($form, $form_state, $section_storage, $delta, $region, $uuid);
     $form_state->set('section_storage', $section_storage);
 
+    // Auto-submit block property changes in the sidebar.
+    $block_properties = array_diff_key($form['settings'], array_flip(['provider', 'block_form', 'context_mapping']));
+    foreach ($block_properties as $property => $_) {
+      $form_item =& $form['settings'][$property];
+      if ($form_item['#type'] !== 'item') {
+        $form_item['#attributes']['data-edit-plus-auto-submit'] = '';
+      }
+    }
+
     $form['actions']['submit']['#attributes']['class'][] = 'edit-plus-update-button';
     $form['actions']['submit']['#ajax']['progress'] = ['type' => 'fullscreen'];
     $form['actions']['submit']['#attributes']['class'][] = 'edit-plus-hidden';
@@ -147,26 +156,6 @@ class UpdateBlockForm extends UpdateBlockFormBase implements EntityFormInterface
    */
   public function submitForm(array &$form, FormStateInterface $form_state) {
     parent::submitForm($form, $form_state);
-    // @todo Uhm, delete this?
-//    // Submit the plugin form.
-//    $subform_state = SubformState::createForSubform($form['settings'], $form, $form_state);
-//    $this->getPluginForm($this->block)->submitConfigurationForm($form, $subform_state);
-//
-//    // If this block is context-aware, set the context mapping.
-//    if ($this->block instanceof ContextAwarePluginInterface) {
-//      $this->block->setContextMapping($subform_state->getValue('context_mapping', []));
-//    }
-//
-//    // Get the submitted configuration.
-//    $configuration = $this->block->getConfiguration();
-//
-//    // Update the block in the current section storage.
-//    $current_section_storage = $form_state->getStorage()['current_section_storage'];
-//    $current_section_storage->getSection($this->delta)->getComponent($this->uuid)->setConfiguration($configuration);
-//
-//    // Update the parent entity section storage.
-//    $this->messenger()->addWarning($this->t('You have unsaved changes.'));
-//    $form_state->setRebuild(TRUE);
 
     // Clear the page cache.
     $parent_entity = $this->getMainEntity($form, $form_state);
@@ -182,8 +171,8 @@ class UpdateBlockForm extends UpdateBlockFormBase implements EntityFormInterface
     $entity = $form_state->getStorage()['section_storage']->getContextValue('entity');
     $this->buildBottomBar($entity, $response);
     $this->renderMessages($response);
-    $this->updateForm($response, $form, $form_state);
     $this->updatePage($response, $form, $form_state);
+    $this->updateForm($response, $form, $form_state);
 
     return $response;
   }
@@ -213,7 +202,7 @@ class UpdateBlockForm extends UpdateBlockFormBase implements EntityFormInterface
   /**
    * {@inheritdoc}
    */
-  public function entityContent(array &$form, FormStateInterface $form_state, string $view_mode) {
+  public function entityContent(array &$form, FormStateInterface $form_state, string $view_mode = NULL) {
     $component = $this->getComponent($form, $form_state);
     $contexts = ['layout_builder.entity' => EntityContext::fromEntity($this->getMainEntity($form, $form_state))];
     return [
diff --git a/src/EditPlusFormTrait.php b/src/EditPlusFormTrait.php
index e4e5661..c96c8c1 100644
--- a/src/EditPlusFormTrait.php
+++ b/src/EditPlusFormTrait.php
@@ -12,13 +12,7 @@ use Drupal\Core\Entity\EntityInterface;
 use Drupal\edit_plus\Ajax\UpdateMarkup;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\edit_plus\Event\AddEmptyField;
-use Drupal\Core\Render\RendererInterface;
 use Drupal\edit_plus\Event\FieldAttributes;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
-use Symfony\Component\EventDispatcher\EventDispatcherInterface;
-use Drupal\field_sample_value\SampleValueEntityGeneratorInterface;
 
 trait EditPlusFormTrait {
 
@@ -38,6 +32,9 @@ trait EditPlusFormTrait {
         'id' => 'empty-field',
       ],
     ];
+
+    // @todo Shouldn't adding this button just be a FieldAttributes event?
+    // @todo or is it special for some reason?
     foreach ($entity->getFieldDefinitions() as $field_name => $field_definition) {
       if (!empty($form[$field_name])) {
         $this->addFieldToPageButton($form, $entity, $field_name);
@@ -59,6 +56,7 @@ trait EditPlusFormTrait {
     $entity = $this->getFormEntity($form, $form_state);
     $entity = $this->editPlusTempstoreRepository->get($entity);
     $view_mode = $this->getViewMode($form, $form_state, $entity);
+    // Add attributes to associate the form item with the rendered markup.
     foreach ($entity->getFieldDefinitions() as $field_name => $field_definition) {
       if (!empty($form[$field_name])) {
         $event = new FieldAttributes($form, $view_mode, $field_name, $entity, $form_state);
@@ -161,10 +159,39 @@ trait EditPlusFormTrait {
     $entity = $this->getFormEntity($form, $form_state);
     $view_mode = $this->getViewMode($form, $form_state, $entity);
     $content = $this->entityContent($form, $form_state, $view_mode);
+    if (!empty($content['component']['content']['#view_mode']) && $content['component']['content']['#view_mode'] !== $view_mode) {
+      // It's possible that the view mode was changed in this update. $view_mode
+      // needs to remain as it was for replacing the old content on the page, but
+      // let's update the view mode for passing it on down the line.
+      if (!empty($form['settings']['block_form']['view_mode']['#value'])) {
+        // @todo This only covers inline blocks I think since it looks for the new view mode in component > content > #view_mode. Ensure that we don't need to cover other situations like entity forms.
+        $form['settings']['block_form']['view_mode']['#value'] = $content['component']['content']['#view_mode'];
+      }
+      $input = $this->getUserInput($form_state);
+      $input['view_mode'] = $content['component']['content']['#view_mode'];
+      $form_state->setUserInput($input);
+    }
+
+    // @todo On call to action you can change the view mode, then this wrapper ID is wrong 😑
     $selector = sprintf('[data-toolbar-plus-entity-wrapper="%s::%s::%s::%s"]', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity), $view_mode, $entity->bundle());
     $response->addCommand(new UpdateMarkup($selector, $content));
   }
 
+  /**
+   * Entity Content
+   *
+   * @param array $form
+   *   The form.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The form state.
+   * @param string|NULL $view_mode
+   *   The view mode.
+   *
+   * @return array
+   *   A render array of the entity content to return as the updated page.
+   */
+  abstract public function entityContent(array &$form, FormStateInterface $form_state, string $view_mode = NULL);
+
   /**
    * Update the entity form.
    *
@@ -294,7 +321,7 @@ trait EditPlusFormTrait {
       $view_mode = $input['view_mode'] ?? NULL;
     }
     if (empty($view_mode)) {
-      $view_mode = 'full';
+      $view_mode = 'default';
     }
 
     // Pass the view mode along to subsequent page requests.
diff --git a/src/EventSubscriber/HandleFieldAttribute.php b/src/EventSubscriber/HandleFieldAttribute.php
index 08fee87..2a3d695 100644
--- a/src/EventSubscriber/HandleFieldAttribute.php
+++ b/src/EventSubscriber/HandleFieldAttribute.php
@@ -10,9 +10,14 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
  * Handle field attribute.
+ *
+ * The "handle" is what DOM element will be used when swapping the form item
+ * into the markup of the page for editing. Options:
+ *  - form_item:
  */
 class HandleFieldAttribute implements EventSubscriberInterface {
 
+
   public function addFormItemAttributesAlter(FieldAttributes $event) {
     $form = $event->getForm();
     $entity = $event->getEntity();
diff --git a/src/Form/InlineEntityFormAlter.php b/src/Form/InlineEntityFormAlter.php
index cf36304..72fdc19 100644
--- a/src/Form/InlineEntityFormAlter.php
+++ b/src/Form/InlineEntityFormAlter.php
@@ -170,7 +170,7 @@ class InlineEntityFormAlter implements EntityFormInterface {
   /**
    * {@inheritdoc}
    */
-  public function entityContent(array &$form, FormStateInterface $form_state, string $view_mode) {
+  public function entityContent(array &$form, FormStateInterface $form_state, string $view_mode = NULL) {
     $entity = $this->editPlusTempstoreRepository->get($form_state->getFormObject()->getEntity());
     return $this->entityTypeManager->getViewBuilder($entity->getEntityTypeId())->view($entity, $view_mode);
   }
-- 
GitLab


From 8eda99d3fe471b1bc27f97c3868142f06b74fe32 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Fri, 6 Sep 2024 15:01:04 -0700
Subject: [PATCH 08/33] Inline edit block label

---
 edit_plus.module                              | 15 ++++-
 .../edit_plus_lb/src/Form/UpdateBlockForm.php | 60 ++++++++++++++++---
 .../MultipleEntityFormController.php          |  3 +
 src/EditPlusFormTrait.php                     |  3 +
 4 files changed, 71 insertions(+), 10 deletions(-)

diff --git a/edit_plus.module b/edit_plus.module
index 64daabc..f5d71e7 100644
--- a/edit_plus.module
+++ b/edit_plus.module
@@ -96,7 +96,20 @@ function edit_plus_preprocess_field(&$variables) {
  * Implements hook_preprocess_HOOK().
  */
 function edit_plus_preprocess_block(&$variables) {
-  $break_point = TRUE; // @todo Remove!
+  $variables['#cache']['contexts'][] = 'user.permissions';
+  if (!\Drupal::currentUser()->hasPermission('access inline editing') || $variables['base_plugin_id'] !== 'inline_block') {
+    return;
+  }
+  // Allow block labels to be edited inline.
+  // @see UpdateBlockForm
+  $entity = $variables['elements']['content']['#block_content'];
+  $id = edit_plus_entity_identifier($entity);
+  $view_mode = _edit_plus_get_view_mode($entity, $variables['content']['#view_mode']);
+  $variables['title_prefix']['#markup'] = sprintf('<div data-edit-plus-field-value-wrapper="%s::%s::label::block_property">', $entity->getEntityTypeId(), $id);
+  $variables['title_suffix']['#markup'] = '</div>';
+  $variables['title_attributes']['class'][] = 'edit-plus-field-value';
+  $variables['title_attributes']['data-edit-plus-id'] = sprintf('%s::%s::%s::%s::%s::%s::%s::%s::%s', $entity->getEntityTypeId(), $id, 'label', 0, $entity->language()->getId(), $view_mode, 'string', 'string', 'block_property');
+  $variables['title_attributes']['data-edit-plus-page-element-id'] = sprintf('%s::%s::%s::%s::%s', $entity->getEntityTypeId(), $id, 'label', 0, 'block_property');
 }
 
 function getCacheTag($entity) {
diff --git a/modules/edit_plus_lb/src/Form/UpdateBlockForm.php b/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
index 5c69677..7beed46 100644
--- a/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
+++ b/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
@@ -87,22 +87,16 @@ class UpdateBlockForm extends UpdateBlockFormBase implements EntityFormInterface
     $form = parent::buildForm($form, $form_state, $section_storage, $delta, $region, $uuid);
     $form_state->set('section_storage', $section_storage);
 
-    // Auto-submit block property changes in the sidebar.
-    $block_properties = array_diff_key($form['settings'], array_flip(['provider', 'block_form', 'context_mapping']));
-    foreach ($block_properties as $property => $_) {
-      $form_item =& $form['settings'][$property];
-      if ($form_item['#type'] !== 'item') {
-        $form_item['#attributes']['data-edit-plus-auto-submit'] = '';
-      }
-    }
-
     $form['actions']['submit']['#attributes']['class'][] = 'edit-plus-update-button';
     $form['actions']['submit']['#ajax']['progress'] = ['type' => 'fullscreen'];
     $form['actions']['submit']['#attributes']['class'][] = 'edit-plus-hidden';
 
     $form['settings']['block_form']['#process'][] = [$this, 'processBlockForm'];
+    $form['#after_build'][] = [$this, 'autoSubmitProperties'];
     $form['#after_build'][] = [$this, 'wrapFormAfterBuild'];
 
+    $this->attributeLabel($form, $form_state);
+
     return $form;
   }
 
@@ -283,4 +277,52 @@ class UpdateBlockForm extends UpdateBlockFormBase implements EntityFormInterface
     return $block_content;
   }
 
+  protected function attributeLabel(array &$form, FormStateInterface $form_state) {
+    $entity = $this->getFormEntity($form, $form_state);
+    $form_item_id = sprintf('%s::%s::%s::%s::%s', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity), 'label', 0, 'block_property');
+    $form['settings']['label']['#wrapper_attributes']['data-edit-plus-form-item-id'] = $form_item_id;
+    $form['settings']['label']['#wrapper_attributes']['class'][] = 'edit-plus-form-item';
+    $form['settings']['label']['#attributes']['data-edit-plus-input'] =  $form_item_id;;
+    $form['settings']['label_wrapper'] = [
+      '#type' => 'container',
+      'label' => $form['settings']['label'],
+      '#attributes' => [
+        'data-edit-plus-form-item-wrapper-id' => sprintf('%s::%s::%s::%s', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity), 'label', 'block_property'),
+        'data-edit-plus-form-item-widget' => 'string_textfield',
+        'class' => ['edit-plus-form-item-wrapper'],
+      ],
+      // This ensures the value is stored under $values['settings']['label']
+      // even though we added a wrapper.
+      '#parents' => ['settings'],
+    ];
+    unset($form['settings']['label']);
+
+  }
+
+  //
+
+  /**
+   * Auto-submit properties.
+   *
+   * Attribute block properties so they can be auto-saved when changed in the sidebar.
+   *
+   * @param array $form
+   *   The block form.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The form state.
+   *
+   * @return array
+   *   The block form.
+   */
+  public function autoSubmitProperties(array &$form, FormStateInterface $form_state) {
+    $block_properties = array_diff(Element::children($form['settings']), ['label', 'provider', 'block_form', 'context_mapping']);
+    foreach ($block_properties as $property) {
+      $form_item =& $form['settings'][$property];
+      if ($form_item['#type'] !== 'item') {
+        $form_item['#attributes']['data-edit-plus-auto-submit'] = '';
+      }
+    }
+    return $form;
+  }
+
 }
diff --git a/src/Controller/MultipleEntityFormController.php b/src/Controller/MultipleEntityFormController.php
index b1d6b7b..15966fa 100644
--- a/src/Controller/MultipleEntityFormController.php
+++ b/src/Controller/MultipleEntityFormController.php
@@ -7,6 +7,7 @@ use Drupal\Core\Form\FormState;
 use Drupal\Core\Ajax\AjaxResponse;
 use Drupal\Core\Ajax\InvokeCommand;
 use Drupal\Core\Ajax\AppendCommand;
+use Drupal\Core\Form\FormStateInterface;
 use Drupal\edit_plus\EditPlusFormTrait;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Controller\ControllerBase;
@@ -88,4 +89,6 @@ final class MultipleEntityFormController extends ControllerBase {
     return $response;
   }
 
+  public function entityContent(array &$form, FormStateInterface $form_state, string $view_mode = NULL) {}
+
 }
diff --git a/src/EditPlusFormTrait.php b/src/EditPlusFormTrait.php
index c96c8c1..d66ee87 100644
--- a/src/EditPlusFormTrait.php
+++ b/src/EditPlusFormTrait.php
@@ -158,6 +158,7 @@ trait EditPlusFormTrait {
   public function updatePage(AjaxResponse $response, array &$form, FormStateInterface $form_state) {
     $entity = $this->getFormEntity($form, $form_state);
     $view_mode = $this->getViewMode($form, $form_state, $entity);
+    $view_mode = _edit_plus_get_view_mode($entity, $view_mode);
     $content = $this->entityContent($form, $form_state, $view_mode);
     if (!empty($content['component']['content']['#view_mode']) && $content['component']['content']['#view_mode'] !== $view_mode) {
       // It's possible that the view mode was changed in this update. $view_mode
@@ -324,6 +325,8 @@ trait EditPlusFormTrait {
       $view_mode = 'default';
     }
 
+
+
     // Pass the view mode along to subsequent page requests.
     if (empty($form['view_mode']['#value'])) {
       $form['view_mode'] = [
-- 
GitLab


From f72f5a2bfd7746ea046ddea47e92c64fb35b4fcc Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Mon, 9 Sep 2024 10:35:41 -0700
Subject: [PATCH 09/33] Allow modules to specify custom properties for inline
 editing.

---
 README.md                                     | 18 ++++-
 edit_plus.module                              |  9 +++
 .../edit_plus_lb/src/Form/UpdateBlockForm.php |  1 +
 src/EditPlusFormTrait.php                     |  3 +
 src/Event/FieldProperties.php                 | 69 +++++++++++++++++++
 src/EventSubscriber/AttributesTrait.php       |  1 +
 .../DefaultFieldAttributes.php                |  6 ++
 templates/block-property.html.twig            |  7 ++
 8 files changed, 111 insertions(+), 3 deletions(-)
 create mode 100644 src/Event/FieldProperties.php
 create mode 100644 templates/block-property.html.twig

diff --git a/README.md b/README.md
index d377776..2d266ac 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,16 @@
-## Edit +
+# Edit +
+Edit+ works by loading the relevant entity form into the sidebar as a "context" sidebar. The form items are hidden. When an editable element is clicked on the page the form item is swapped into place for inline editing.
 
-
-###
+### Associating the Form Item with the Page element
+To make the UI aware of an editable page element it needs to end up with the following markup or provide its own Edit+ field widget JS plugin. There can of course be more to this markup, but these are whats required for inline editing. Please see `edit_plus_preprocess_field()` for details.
+```html
+<div data-edit-plus-field-value-wrapper="block_content::bc74a654-2ba6-447a-a8a0-497776cb2ba4::field_links_links::value">
+  <div class="edit-plus-field-value" data-edit-plus-id="block_content::bc74a654-2ba6-447a-a8a0-497776cb2ba4::field_links_links::0::en::default::link::link::value" data-edit-plus-page-element-id="block_content::bc74a654-2ba6-447a-a8a0-497776cb2ba4::field_links_links::0::value">
+    <a href="https://www.puvaphesw.gov">https://www.puvaphesw.gov</a>
+  </div>
+</div>
+```
+To relate the above editable page element to the form item that was loaded when it was clicked we need the following markup on the form item.
+```html
+<!-- @todo 😅 -->
+```
diff --git a/edit_plus.module b/edit_plus.module
index f5d71e7..4da44f1 100644
--- a/edit_plus.module
+++ b/edit_plus.module
@@ -105,6 +105,15 @@ function edit_plus_preprocess_block(&$variables) {
   $entity = $variables['elements']['content']['#block_content'];
   $id = edit_plus_entity_identifier($entity);
   $view_mode = _edit_plus_get_view_mode($entity, $variables['content']['#view_mode']);
+  // There are two ways to make a block property editable. We special case the
+  // block label here with the prefix and suffix. Modules can also call the
+  // @todo twig function to wrap it.
+  $variables['edit_plus'] = [
+    'id' => $id,
+    'type' => $entity->getEntityTypeId(),
+    'language' => $entity->language()->getId(),
+    'view_mode' => $view_mode,
+  ];
   $variables['title_prefix']['#markup'] = sprintf('<div data-edit-plus-field-value-wrapper="%s::%s::label::block_property">', $entity->getEntityTypeId(), $id);
   $variables['title_suffix']['#markup'] = '</div>';
   $variables['title_attributes']['class'][] = 'edit-plus-field-value';
diff --git a/modules/edit_plus_lb/src/Form/UpdateBlockForm.php b/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
index 7beed46..12d5c04 100644
--- a/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
+++ b/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
@@ -282,6 +282,7 @@ class UpdateBlockForm extends UpdateBlockFormBase implements EntityFormInterface
     $form_item_id = sprintf('%s::%s::%s::%s::%s', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity), 'label', 0, 'block_property');
     $form['settings']['label']['#wrapper_attributes']['data-edit-plus-form-item-id'] = $form_item_id;
     $form['settings']['label']['#wrapper_attributes']['class'][] = 'edit-plus-form-item';
+    $form['settings']['label']['#wrapper_attributes']['class'][] = 'edit-plus-hidden';
     $form['settings']['label']['#attributes']['data-edit-plus-input'] =  $form_item_id;;
     $form['settings']['label_wrapper'] = [
       '#type' => 'container',
diff --git a/src/EditPlusFormTrait.php b/src/EditPlusFormTrait.php
index d66ee87..7104a76 100644
--- a/src/EditPlusFormTrait.php
+++ b/src/EditPlusFormTrait.php
@@ -167,7 +167,10 @@ trait EditPlusFormTrait {
       if (!empty($form['settings']['block_form']['view_mode']['#value'])) {
         // @todo This only covers inline blocks I think since it looks for the new view mode in component > content > #view_mode. Ensure that we don't need to cover other situations like entity forms.
         $form['settings']['block_form']['view_mode']['#value'] = $content['component']['content']['#view_mode'];
+        // @todo View modes are all over the place and we keep ending up with "full" from a field and then falling back to "default"
+        // @todo is this an example of where it's always right? Maybe this can be the way everything works and consolidate it in _edit_plus_get_view_mode
       }
+
       $input = $this->getUserInput($form_state);
       $input['view_mode'] = $content['component']['content']['#view_mode'];
       $form_state->setUserInput($input);
diff --git a/src/Event/FieldProperties.php b/src/Event/FieldProperties.php
new file mode 100644
index 0000000..d8fd4bc
--- /dev/null
+++ b/src/Event/FieldProperties.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace Drupal\edit_plus\Event;
+
+use Drupal\Component\EventDispatcher\Event;
+use Drupal\Core\Entity\EntityInterface;
+
+class FieldProperties extends Event {
+
+  /**
+   * An array of field properties.
+   */
+  private array $properties;
+
+  /**
+   * @var \Drupal\Core\Entity\EntityInterface
+   */
+  private EntityInterface $entity;
+
+  /**
+   * The field name.
+   */
+  private string $fieldName;
+
+  public function __construct(EntityInterface $entity, string $field_name, array $properties) {
+    $this->properties = $properties;
+    $this->entity = $entity;
+    $this->fieldName = $field_name;
+  }
+
+  /**
+   * Get properties.
+   *
+   * @return
+   *   An array of properties on this field.
+   */
+  public function getProperties() {
+    return $this->properties;
+  }
+
+  /**
+   * @param array $properties
+   *   An array of field properties.
+   */
+  public function setProperties(array $properties) {
+    $this->properties = $properties;
+  }
+
+  /**
+   * Get entity.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface
+   *   The entity that this field is on.
+   */
+  public function getEntity(): EntityInterface {
+    return $this->entity;
+  }
+
+  /**
+   * Get field name.
+   *
+   * @return string
+   *   The field name.
+   */
+  public function getFieldName(): string {
+    return $this->fieldName;
+  }
+
+}
diff --git a/src/EventSubscriber/AttributesTrait.php b/src/EventSubscriber/AttributesTrait.php
index 785fd71..c4547b2 100644
--- a/src/EventSubscriber/AttributesTrait.php
+++ b/src/EventSubscriber/AttributesTrait.php
@@ -14,6 +14,7 @@ trait AttributesTrait {
     if (empty($form_display))  {
       // Must not be an entity form, load the form display.
       $entity = $event->getEntity();
+      // @todo Use an abstract getter method for dependency injection.
       $form_display = \Drupal::service('entity_display.repository')->getFormDisplay($entity->getEntityTypeId(), $entity->bundle());
     }
 
diff --git a/src/EventSubscriber/DefaultFieldAttributes.php b/src/EventSubscriber/DefaultFieldAttributes.php
index 7b2881d..334d5d4 100644
--- a/src/EventSubscriber/DefaultFieldAttributes.php
+++ b/src/EventSubscriber/DefaultFieldAttributes.php
@@ -9,6 +9,7 @@ use Drupal\Core\Template\Attribute;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\edit_plus\Event\FieldAttributes;
+use Drupal\edit_plus\Event\FieldProperties;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
@@ -46,7 +47,12 @@ class DefaultFieldAttributes implements EventSubscriberInterface {
     $entity = $event->getEntity();
     $field_name = $event->getFieldName();
     $form_item = &$form[$field_name];
+
     $properties = $entity->getFieldDefinition($field_name)->getFieldStorageDefinition()->getPropertyNames();
+    // Allow modules to specify custom properties.
+    // @todo Use an abstract getter method for dependency injection.
+    $properties = \Drupal::service('event_dispatcher')->dispatch(new FieldProperties($entity, $field_name, $properties), FieldProperties::class)->getProperties();
+
     if (!empty($form_item['widget']['#theme']) && $form_item['widget']['#theme'] === 'field_multiple_value_form') {
       foreach (Element::children($form_item['widget']) as $delta) {
         foreach ($properties as $property) {
diff --git a/templates/block-property.html.twig b/templates/block-property.html.twig
new file mode 100644
index 0000000..1af55ac
--- /dev/null
+++ b/templates/block-property.html.twig
@@ -0,0 +1,7 @@
+{% macro wrapper(edit_plus, type, formatter, name, property) %}
+  <div data-edit-plus-field-value-wrapper="{{ edit_plus.type }}::{{ edit_plus.id }}::{{ name }}::block_property">
+    <div class="edit-plus-field-value" data-edit-plus-id="{{ edit_plus.type }}::{{ edit_plus.id }}::{{ name }}::0::{{ edit_plus.language }}::{{ edit_plus.view_mode }}::{{ type }}::{{ formatter }}::block_property" data-edit-plus-page-element-id="{{ edit_plus.type }}::{{ edit_plus.id }}::{{ name }}::0::block_property">
+      {{ property }}
+    </div>
+  </div>
+{% endmacro %}
-- 
GitLab


From 5961fd1af81279b4b3606b5198dfa19ff7186b03 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Tue, 10 Sep 2024 12:28:14 -0700
Subject: [PATCH 10/33] Resolve layout builder view modes before falling back.

---
 edit_plus.module                              | 50 ++++---------------
 .../edit_plus_lb/src/Form/UpdateBlockForm.php |  1 +
 src/EditPlusFormTrait.php                     |  7 ++-
 3 files changed, 13 insertions(+), 45 deletions(-)

diff --git a/edit_plus.module b/edit_plus.module
index 4da44f1..4c2b610 100644
--- a/edit_plus.module
+++ b/edit_plus.module
@@ -52,22 +52,23 @@ function edit_plus_preprocess_field(&$variables) {
     }
   }
 
-  // Edit+ only supports view modes, not dynamically defined
-  // "display options" (which \Drupal\Core\Field\FieldItemListInterface::view()
-  // always names the "_custom" view mode).
-  // @see \Drupal\Core\Field\FieldItemListInterface::view()
-  // @see https://www.drupal.org/node/2120335
-  $view_mode = _edit_plus_get_view_mode($entity, $element['#view_mode']);
+  $view_mode = $element['#view_mode'];
   if ($view_mode === '_custom') {
     // Support layout builder field blocks.
     if (!empty($element['#third_party_settings']['layout_builder']['view_mode'])) {
       $view_mode = $element['#third_party_settings']['layout_builder']['view_mode'];
     }
     else {
+      // Layout Builder (and Edit+) only supports view modes, not dynamically defined
+      // "display options" (which \Drupal\Core\Field\FieldItemListInterface::view()
+      // always names the "_custom" view mode).
+      // @see \Drupal\Core\Field\FieldItemListInterface::view()
+      // @see https://www.drupal.org/node/2120335
       return;
     }
   }
-
+  // Get the actual view mode.
+  $view_mode = _toolbar_plus_get_view_mode($entity, $view_mode);
   $definition = $entity->getFieldDefinition($element['#field_name']);
   $main_property = method_exists($definition, 'getMainPropertyName') ? $definition->getMainPropertyName() : 'value';
   $id = edit_plus_entity_identifier($entity);
@@ -104,7 +105,7 @@ function edit_plus_preprocess_block(&$variables) {
   // @see UpdateBlockForm
   $entity = $variables['elements']['content']['#block_content'];
   $id = edit_plus_entity_identifier($entity);
-  $view_mode = _edit_plus_get_view_mode($entity, $variables['content']['#view_mode']);
+  $view_mode = _toolbar_plus_get_view_mode($entity, $variables['content']['#view_mode']);
   // There are two ways to make a block property editable. We special case the
   // block label here with the prefix and suffix. Modules can also call the
   // @todo twig function to wrap it.
@@ -227,38 +228,5 @@ function edit_plus_form_field_config_edit_form_alter(&$form, FormStateInterface
   \Drupal::service('edit_plus.field_config_form_alter')->formAlter($form, $form_state);
 }
 
-/**
- * Edit plus get view mode.
- *
- * Falls back to a view mode that exists for this entity.
- * @todo this needs to be consolidated with the other view mode handling.
- *
- * @param \Drupal\Core\Entity\EntityInterface $entity
- *   The entity.
- * @param string|NULL $view_mode
- *   The perspective view mode.
- *
- * @return string
- *   The view mode.
- *
- * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
- * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
- */
-function _edit_plus_get_view_mode(EntityInterface $entity, string $view_mode = NULL): string {
-  static $cached_view_modes;
-  $original_id = $entity->getEntityTypeId() . "." . $entity->bundle() . "." . $view_mode;
-
-  if (!empty($cached_view_modes[$original_id])) {
-    return $cached_view_modes[$original_id];
-  }
 
-  $storage = \Drupal::entityTypeManager()->getStorage('entity_view_display');
-  $view_display = $storage->load($original_id);
-  if (empty($view_display)) {
-    $default_id = $entity->getEntityTypeId() . "." . $entity->bundle() . ".default";
-    $view_display = $storage->load($default_id);
-  }
-  $cached_view_modes[$original_id] = $view_display->getMode();
-  return $cached_view_modes[$original_id];
-}
 
diff --git a/modules/edit_plus_lb/src/Form/UpdateBlockForm.php b/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
index 12d5c04..caafaad 100644
--- a/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
+++ b/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
@@ -202,6 +202,7 @@ class UpdateBlockForm extends UpdateBlockFormBase implements EntityFormInterface
     return [
       // Add a wrapper so Drupal.behaviors.EditPlusEnable can find the
       // entity wrapper which is context in this case.
+      // @todo Could you do an alternative once like in inline-editor.js attachEditor instead?
       '#type' => 'container',
       'component' => $component->toRenderArray($contexts),
     ];
diff --git a/src/EditPlusFormTrait.php b/src/EditPlusFormTrait.php
index 7104a76..d79ca59 100644
--- a/src/EditPlusFormTrait.php
+++ b/src/EditPlusFormTrait.php
@@ -158,7 +158,7 @@ trait EditPlusFormTrait {
   public function updatePage(AjaxResponse $response, array &$form, FormStateInterface $form_state) {
     $entity = $this->getFormEntity($form, $form_state);
     $view_mode = $this->getViewMode($form, $form_state, $entity);
-    $view_mode = _edit_plus_get_view_mode($entity, $view_mode);
+    $view_mode = _toolbar_plus_get_view_mode($entity, $view_mode);
     $content = $this->entityContent($form, $form_state, $view_mode);
     if (!empty($content['component']['content']['#view_mode']) && $content['component']['content']['#view_mode'] !== $view_mode) {
       // It's possible that the view mode was changed in this update. $view_mode
@@ -168,7 +168,7 @@ trait EditPlusFormTrait {
         // @todo This only covers inline blocks I think since it looks for the new view mode in component > content > #view_mode. Ensure that we don't need to cover other situations like entity forms.
         $form['settings']['block_form']['view_mode']['#value'] = $content['component']['content']['#view_mode'];
         // @todo View modes are all over the place and we keep ending up with "full" from a field and then falling back to "default"
-        // @todo is this an example of where it's always right? Maybe this can be the way everything works and consolidate it in _edit_plus_get_view_mode
+        // @todo is this an example of where it's always right? Maybe this can be the way everything works and consolidate it in _toolbar_plus_get_view_mode
       }
 
       $input = $this->getUserInput($form_state);
@@ -309,8 +309,6 @@ trait EditPlusFormTrait {
    *   The view mode of the entity being edited.
    */
   public function getViewMode(array &$form, FormStateInterface $form_state, EntityInterface $entity) {
-    $input = $this->getUserInput($form_state);
-
     // View mode comes from the initial JS that loads the form or from the previously
     // loaded form for subsequent form loads. e.g. Adding an empty field to the page.
     $view_mode = $this->request->get('viewMode');
@@ -322,6 +320,7 @@ trait EditPlusFormTrait {
         throw new \InvalidArgumentException((string) t('Edit +: Invalid view mode for @label', ['@label' => $entity->label()]));
       }
     } else {
+      $input = $this->getUserInput($form_state);
       $view_mode = $input['view_mode'] ?? NULL;
     }
     if (empty($view_mode)) {
-- 
GitLab


From 43200359f7194a682a7968606bf59952f75d1438 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Tue, 10 Sep 2024 15:52:47 -0700
Subject: [PATCH 11/33] Set the forms hidden view mode input in tempstore
 update so that we don't need to update the form on every edit

---
 css/edit-plus.css                             |  5 ++
 edit_plus.services.yml                        | 14 ++----
 js/edit_plus/entity-form.js                   | 15 ++++++
 js/edit_plus/fields/field-plugin-base.js      |  1 +
 js/edit_plus/utilities.js                     | 17 ++++++-
 .../edit_plus_lb/src/Form/UpdateBlockForm.php |  4 +-
 src/EditPlusFormTrait.php                     | 49 ++++++++++---------
 7 files changed, 70 insertions(+), 35 deletions(-)

diff --git a/css/edit-plus.css b/css/edit-plus.css
index 7121c59..5dbea2d 100644
--- a/css/edit-plus.css
+++ b/css/edit-plus.css
@@ -34,3 +34,8 @@ div.edit-plus-hidden {
   from { background-color: rgba(121, 189, 143, 1)}
   to { background-color: rgba(121, 189, 143, 0)}
 }
+
+/* @todo Remove when we stop using block decorators. */
+.block .button.js-hide {
+  display: none;
+}
diff --git a/edit_plus.services.yml b/edit_plus.services.yml
index 587ef0e..eb93435 100644
--- a/edit_plus.services.yml
+++ b/edit_plus.services.yml
@@ -1,4 +1,8 @@
 services:
+  _defaults:
+    autoconfigure: true
+    autowire: true
+
   edit_plus.inline_entity_form:
     class: Drupal\edit_plus\Form\InlineEntityFormAlter
     arguments: ['@entity_display.repository', '@edit_plus.tempstore_repository', '@field_sample_value.generator', '@entity_type.manager', '@event_dispatcher', '@module_handler', '@renderer', '@request_stack', '@edit_plus.ui' ]
@@ -28,25 +32,15 @@ services:
 
   edit_plus.event_subscriber.default_field_attributes:
     class: Drupal\edit_plus\EventSubscriber\DefaultFieldAttributes
-    tags:
-      - { name: event_subscriber }
 
   edit_plus.event_subscriber.handle_field_attribute:
     class: Drupal\edit_plus\EventSubscriber\HandleFieldAttribute
-    tags:
-      - { name: event_subscriber }
 
   edit_plus.event_subscriber.inline_editor_field_attributes:
     class: Drupal\edit_plus\EventSubscriber\InlineEditorFieldAttributes
-    tags:
-      - { name: event_subscriber }
 
   edit_plus.event_subscriber.media_field_attributes:
     class: Drupal\edit_plus\EventSubscriber\MediaFieldAttributes
-    tags:
-      - { name: event_subscriber }
 
   edit_plus.event_subscriber.clone_field_attribute:
     class: Drupal\edit_plus\EventSubscriber\CloneFieldAttribute
-    tags:
-      - { name: event_subscriber }
diff --git a/js/edit_plus/entity-form.js b/js/edit_plus/entity-form.js
index 1a9eda7..1bcd373 100644
--- a/js/edit_plus/entity-form.js
+++ b/js/edit_plus/entity-form.js
@@ -185,6 +185,21 @@ export const updateTempstore = (EditableElement, isEmpty, form = null) => {
     form.querySelector('#empty-field').value = EditableElement.info.fieldName;
   }
 
+  // Update the hidden view mode input.
+  let viewMode;
+  if (EditableElement) {
+    // I think we can standardize on getting the view mode from the form > entity
+    // wrapper relationship, but we might as well get it from EditableElement
+    // when it's available as it's a tiny bit faster.
+    viewMode = EditableElement.info.viewMode;
+  } else {
+    // EditableElement won't be available when submitting the form via EditPlusEntityFormAutoSave.
+    const entityWrapper = document.querySelector('[data-toolbar-plus-entity-wrapper^="' + form.closest('.edit-plus-form').dataset.editPlusFormId + '"]')
+    const info = utilities.parseEntityWrapperId(entityWrapper.dataset.toolbarPlusEntityWrapper);
+    viewMode = info.viewMode;
+  }
+  form.querySelector('.edit-plus-view-mode').value = viewMode;
+
   // Click the update button (formerly the save submit).
   const updateButton = form.querySelector('.edit-plus-update-button');
   jQuery(updateButton).mousedown();
diff --git a/js/edit_plus/fields/field-plugin-base.js b/js/edit_plus/fields/field-plugin-base.js
index eb9f890..ce2cf49 100644
--- a/js/edit_plus/fields/field-plugin-base.js
+++ b/js/edit_plus/fields/field-plugin-base.js
@@ -247,6 +247,7 @@ export class FieldPluginBase {
     // its attributes so the clone is no longer a duplicate of the form item
     // which might confuse JS.
     clone.id = this.getClonedElementId(clone);
+    clone.classList.add('edit-plus-clone');
     clone.setAttribute('data-edit-plus-clone-id', 'handle');
     const handleChildren = formElementHandle.querySelectorAll('*');
     const cloneChildren = clone.querySelectorAll('*');
diff --git a/js/edit_plus/utilities.js b/js/edit_plus/utilities.js
index 20db3a0..48c3f37 100644
--- a/js/edit_plus/utilities.js
+++ b/js/edit_plus/utilities.js
@@ -20,13 +20,22 @@ export const parseMarkupId = (id) => {
     langcode: parts[4],
     viewMode: parts[5],
     fieldType: parts[6],
-    // widget: parts[7],
     fieldFormatter: parts[7],
     mainProperty: parts[8],
     elementId: id,
   };
 }
 
+export const parseEntityWrapperId = (id) => {
+  const parts = id.split('::');
+  return {
+    entityTypeId: parts[0],
+    entityId: parts[1],
+    viewMode: parts[2],
+    bundle: parts[3],
+  };
+}
+
 /**
  * Parse Form Item ID.
  *
@@ -189,4 +198,8 @@ jQuery.fn.EditPlusUpdateMarkup = (selector, content) => {
     entityWrapper.outerHTML = content;
   }
   Drupal.EditPlus.EnableEditMode();
-};
+  const breakPoint = true; // @todo Remove!
+  // @todo between here and page load complete we loose all
+  // document.querySelectorAll('[data-edit-plus-original-id]')
+  // When making a change in the CTA and then clicking the eyebrow.
+}
diff --git a/modules/edit_plus_lb/src/Form/UpdateBlockForm.php b/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
index caafaad..bd7fe4f 100644
--- a/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
+++ b/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
@@ -166,7 +166,6 @@ class UpdateBlockForm extends UpdateBlockFormBase implements EntityFormInterface
     $this->buildBottomBar($entity, $response);
     $this->renderMessages($response);
     $this->updatePage($response, $form, $form_state);
-    $this->updateForm($response, $form, $form_state);
 
     return $response;
   }
@@ -285,6 +284,9 @@ class UpdateBlockForm extends UpdateBlockFormBase implements EntityFormInterface
     $form['settings']['label']['#wrapper_attributes']['class'][] = 'edit-plus-form-item';
     $form['settings']['label']['#wrapper_attributes']['class'][] = 'edit-plus-hidden';
     $form['settings']['label']['#attributes']['data-edit-plus-input'] =  $form_item_id;;
+//    if (empty($form['settings']['label']['#attributes']['id'])) {
+//      $form['settings']['label']['#attributes']['id'] = Html::getUniqueId($form_item_id);
+//    }
     $form['settings']['label_wrapper'] = [
       '#type' => 'container',
       'label' => $form['settings']['label'],
diff --git a/src/EditPlusFormTrait.php b/src/EditPlusFormTrait.php
index d79ca59..f07baaf 100644
--- a/src/EditPlusFormTrait.php
+++ b/src/EditPlusFormTrait.php
@@ -33,6 +33,13 @@ trait EditPlusFormTrait {
       ],
     ];
 
+    // Pass the view mode along to subsequent page requests.
+    $form['view_mode'] = [
+      '#type' => 'hidden',
+      '#attributes' => ['class' => ['edit-plus-view-mode']],
+      '#value' => $this->getViewMode($form, $form_state, $entity),
+    ];
+
     // @todo Shouldn't adding this button just be a FieldAttributes event?
     // @todo or is it special for some reason?
     foreach ($entity->getFieldDefinitions() as $field_name => $field_definition) {
@@ -241,7 +248,8 @@ trait EditPlusFormTrait {
   }
 
   public static function getEditPlusFormId(EntityInterface $entity) {
-    return "edit-plus-form_{$entity->getEntityTypeId()}-{$entity->id()}";
+    $id = edit_plus_entity_identifier($entity);
+    return "edit-plus-form_{$entity->getEntityTypeId()}-{$id}";
   }
 
   /**
@@ -312,32 +320,29 @@ trait EditPlusFormTrait {
     // View mode comes from the initial JS that loads the form or from the previously
     // loaded form for subsequent form loads. e.g. Adding an empty field to the page.
     $view_mode = $this->request->get('viewMode');
-    if (!empty($view_mode)) {
-      // Sanitize view mode.
-      $valid_view_modes = $this->entityDisplayRepository->getViewModes($entity->getEntityTypeId());
-      $valid_view_modes['default'] = TRUE;
-      if (empty($valid_view_modes[$view_mode])) {
-        throw new \InvalidArgumentException((string) t('Edit +: Invalid view mode for @label', ['@label' => $entity->label()]));
-      }
-    } else {
-      $input = $this->getUserInput($form_state);
-      $view_mode = $input['view_mode'] ?? NULL;
-    }
     if (empty($view_mode)) {
-      $view_mode = 'default';
+      // When the form is submitted we are going to need to update the rendered page
+      // so we need the view mode. Make the form aware of this value so we can set
+      // it with JS before submitting.
+      $input = $form_state->getUserInput();
+      if (!empty($input['settings']['block_form']['view_mode'])) {
+        // Block content entity form.
+        $view_mode = $input['settings']['block_form']['view_mode'];
+      }
+      elseif (!empty($input['view_mode'])) {
+        // Entity form.
+        $view_mode = $input['view_mode'];
+      }
     }
-
-
-
-    // Pass the view mode along to subsequent page requests.
-    if (empty($form['view_mode']['#value'])) {
-      $form['view_mode'] = [
-        '#type' => 'hidden',
-        '#value' => $view_mode,
-      ];
+    // Sanitize view mode.
+    $valid_view_modes = $this->entityDisplayRepository->getViewModes($entity->getEntityTypeId());
+    $valid_view_modes['default'] = TRUE;
+    if (empty($valid_view_modes[$view_mode])) {
+      throw new \InvalidArgumentException((string) t('Edit +: Invalid view mode for @label', ['@label' => $entity->label()]));
     }
 
     return $view_mode;
   }
 
 }
+
-- 
GitLab


From b569908197a8ae07deef795626811520b75e03c9 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Mon, 16 Sep 2024 08:59:30 -0700
Subject: [PATCH 12/33] Differentiate media widget's field_widget_id by block.

---
 edit_plus.module                              | 11 ++-
 edit_plus.services.yml                        |  8 +-
 js/edit_plus/fields/media.js                  |  6 +-
 src/EventSubscriber/MediaFieldAttributes.php  | 31 ++++++++
 src/Form/ViewsFormMediaLibraryWidgetAlter.php | 76 +++++++++++++++++++
 5 files changed, 125 insertions(+), 7 deletions(-)
 create mode 100644 src/Form/ViewsFormMediaLibraryWidgetAlter.php

diff --git a/edit_plus.module b/edit_plus.module
index 4c2b610..bbf6b86 100644
--- a/edit_plus.module
+++ b/edit_plus.module
@@ -131,13 +131,20 @@ function getCacheTag($entity) {
  */
 function edit_plus_form_alter(&$form, FormStateInterface $form_state, $form_id) {
   if ($form_state->get('edit_plus_form')) {
-    \Drupal::service('edit_plus.inline_entity_form')->formAlter($form, $form_state);
+    \Drupal::service('edit_plus.form_alter.inline_entity_form')->formAlter($form, $form_state);
   }
   else {
-    \Drupal::service('edit_plus.entity_edit_form_alter')->formAlter($form, $form_state);
+    \Drupal::service('edit_plus.form_alter.entity_edit')->formAlter($form, $form_state);
   }
 }
 
+/**
+ * Implements hook_form_BASE_FORM_ID_alter().
+ */
+function edit_plus_form_views_form_media_library_widget_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
+  \Drupal::service('edit_plus.form_alter.views_form_media_library_widget')->formAlter($form, $form_state);
+}
+
 /**
  * Implements hook_module_implements_alter().
  */
diff --git a/edit_plus.services.yml b/edit_plus.services.yml
index eb93435..68d51d4 100644
--- a/edit_plus.services.yml
+++ b/edit_plus.services.yml
@@ -3,14 +3,18 @@ services:
     autoconfigure: true
     autowire: true
 
-  edit_plus.inline_entity_form:
+  edit_plus.form_alter.inline_entity_form:
     class: Drupal\edit_plus\Form\InlineEntityFormAlter
     arguments: ['@entity_display.repository', '@edit_plus.tempstore_repository', '@field_sample_value.generator', '@entity_type.manager', '@event_dispatcher', '@module_handler', '@renderer', '@request_stack', '@edit_plus.ui' ]
 
-  edit_plus.entity_edit_form_alter:
+  edit_plus.form_alter.entity_edit:
     class: Drupal\edit_plus\Form\EntityEditFormAlter
     arguments: [ '@edit_plus.tempstore_repository' , '@current_route_match']
 
+  # @todo Rename the above form alters to match the following new convention.
+  edit_plus.form_alter.views_form_media_library_widget:
+    class: Drupal\edit_plus\Form\ViewsFormMediaLibraryWidgetAlter
+
   edit_plus.field_config_form_alter:
     class: Drupal\edit_plus\Form\FieldConfigFormAlter
 
diff --git a/js/edit_plus/fields/media.js b/js/edit_plus/fields/media.js
index 01b5ec0..ae5f0b2 100644
--- a/js/edit_plus/fields/media.js
+++ b/js/edit_plus/fields/media.js
@@ -18,14 +18,14 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
       'media_library_widget',
     ];
     focusElement(EditableElement) {
-      this.originalValue = EditableElement.getFormItemWrapper().querySelector('.edit-plus-field-value img').src;
+      this.originalValue = EditableElement.getFormItemWrapper().querySelector('.edit-plus-field-value img')?.src ?? null;
     }
     blurElement(EditableElement) {
       const formItemWrapper = EditableElement.getFormItemWrapper();
-      const newValue = formItemWrapper.querySelector('.edit-plus-field-value img').src
+      const newValue = formItemWrapper.querySelector('.edit-plus-field-value img')?.src ?? null;
 
       this.replaceEditableElementWithMarkup(EditableElement);
-      if (this.originalValue !== newValue) {
+      if (newValue && this.originalValue !== newValue) {
         entityForm.updateTempstore(EditableElement, newValue.length === 0);
       }
     }
diff --git a/src/EventSubscriber/MediaFieldAttributes.php b/src/EventSubscriber/MediaFieldAttributes.php
index e42b129..deb882b 100644
--- a/src/EventSubscriber/MediaFieldAttributes.php
+++ b/src/EventSubscriber/MediaFieldAttributes.php
@@ -4,7 +4,9 @@ declare(strict_types=1);
 
 namespace Drupal\edit_plus\EventSubscriber;
 
+use Drupal\Core\Render\Element;
 use Drupal\edit_plus\Event\FieldAttributes;
+use Drupal\media_library\MediaLibraryState;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
@@ -40,6 +42,35 @@ class MediaFieldAttributes implements EventSubscriberInterface {
       $form_item['widget']['#attributes']['class'][] = 'edit-plus-form-item';
       $form_item['widget']['#attributes']['data-edit-plus-form-item-id'] = sprintf('%s::%s::%s::%s::%s', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity), $field_name, 0, 'value');
 
+      // There could be multiple identical field widgets on the same page. e.g.
+      // Say we have a custom block with a field_hero_media field on it. If we
+      // have two of the same block types being edited that means two forms on
+      // the page with the same field. The AJAX wrapper in MediaLibraryWidget is
+      // $field_name . '-media-library-wrapper' . $id_suffix; so we'd have duplicate
+      // ID's. Let's add a little more specificity when we are clicking the add and
+      // remove buttons on the block form.
+      // @see https://www.drupal.org/project/drupal/issues/3345064#comment-15774869
+      $wrapper_id = $form_item['widget']['#attributes']['id'] = $form_item['widget']['#attributes']['id']  . '-' . $entity->uuid();
+      foreach (Element::children($form_item['widget']['selection']) as $key) {
+         $form_item['widget']['selection'][$key]['remove_button']['#ajax']['wrapper']
+           = $form_item['widget']['media_library_update_widget']['#ajax']['wrapper']
+           = $wrapper_id;
+      }
+      // Add more specificity when we are clicking the Insert selected button in
+      // the modal.
+      // @see ViewsFormMediaLibraryWidgetAlter
+      $state = $form_item['widget']['open_button']['#media_library_state'];
+      $parameters = $state->getOpenerParameters();
+      if (empty($parameters['field_widget_id'])) {
+        throw new \InvalidArgumentException('field_widget_id parameter is missing.');
+      }
+      $parameters['field_widget_id_and_block_uuid'] = $wrapper_id;
+      $state->add(['media_library_opener_parameters' => $parameters]);
+      $state->set('hash', $state->getHash());
+      $form_item['widget']['media_library_update_widget']['#attributes']['data-media-library-widget-update']
+        = $form_item['widget']['media_library_selection']['#attributes']['data-media-library-widget-value']
+        = $parameters['field_widget_id_and_block_uuid'];
+
       $event->setForm($form);
       $event->stopPropagation();
     }
diff --git a/src/Form/ViewsFormMediaLibraryWidgetAlter.php b/src/Form/ViewsFormMediaLibraryWidgetAlter.php
new file mode 100644
index 0000000..cc39495
--- /dev/null
+++ b/src/Form/ViewsFormMediaLibraryWidgetAlter.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace Drupal\edit_plus\Form;
+
+use Drupal\Core\Ajax\AjaxResponse;
+use Drupal\Core\Ajax\CloseDialogCommand;
+use Drupal\Core\Ajax\InvokeCommand;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\edit_plus\EventSubscriber\HandleFieldAttribute;
+use Drupal\media_library\MediaLibraryState;
+use Drupal\media_library\Plugin\views\field\MediaLibrarySelectForm;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ */
+class ViewsFormMediaLibraryWidgetAlter {
+
+  use StringTranslationTrait;
+
+  /**
+   * Implements hook_form_FORM_ID_alter() for the 'views_form_media_library_widget' form ID.
+   *
+   * @param $form
+   *   Forms.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *  The form state.
+   */
+  public function formAlter(&$form, FormStateInterface $form_state) {
+    $form['actions']['submit']['#ajax']['callback'][0] = static::class;
+  }
+
+  /**
+   * Update widget ajax callback override.
+   *
+   * There could be multiple identical field widgets on the same page. e.g.
+   * Say we have a custom block with a field_hero_media field on it. If we
+   * have two of the same block types being edited that means two forms on
+   * the page with the same field. The AJAX wrapper in MediaLibraryWidget is
+   * $field_name . '-media-library-wrapper' . $id_suffix; so we'd have duplicate
+   * ID's. Let's add a little more specificity when we are clicking the Insert
+   * selected button in the modal.
+   * @see https://www.drupal.org/project/drupal/issues/3345064#comment-15774869
+   *
+   * @param array $form
+   *   The form.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The form state.
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The current request.
+   *
+   * @return \Drupal\Core\Ajax\AjaxResponse
+   *   A modified version of the request from MediaLibrarySelectForm::updateWidget
+   *   and MediaLibraryFieldWidgetOpener->getSelectionResponse that has block
+   *   specific media widget ID selectors.
+   */
+  public static function updateWidget(array &$form, FormStateInterface $form_state, Request $request) {
+    $response = MediaLibrarySelectForm::updateWidget($form, $form_state, $request);
+    $state = MediaLibraryState::fromRequest($request);
+
+    $parameters = $state->getOpenerParameters();
+    if (empty($parameters['field_widget_id_and_block_uuid'])) {
+      throw new \InvalidArgumentException('field_widget_id_and_block_uuid parameter is missing.');
+    }
+
+    $widget_id = $parameters['field_widget_id_and_block_uuid'];
+    $commands = $response->getCommands();
+    $response_with_more_specific_selectors = new AjaxResponse();
+    $response_with_more_specific_selectors
+      ->addCommand(new InvokeCommand("[data-media-library-widget-value='$widget_id']", 'val', $commands[0]['args']))
+      ->addCommand(new InvokeCommand("[data-media-library-widget-update='$widget_id']", 'trigger', ['mousedown']))
+      ->addCommand(new CloseDialogCommand());
+    return $response_with_more_specific_selectors;
+  }
+
+}
-- 
GitLab


From 8c78c20c6d0f23c8b86b95e22d8c5a5fe1f10ced Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Mon, 16 Sep 2024 10:20:42 -0700
Subject: [PATCH 13/33] Show what the differences are in the param converter.

---
 src/ParamConverter/EntityConverter.php | 33 ++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/src/ParamConverter/EntityConverter.php b/src/ParamConverter/EntityConverter.php
index 72921a7..d7c0525 100644
--- a/src/ParamConverter/EntityConverter.php
+++ b/src/ParamConverter/EntityConverter.php
@@ -34,16 +34,41 @@ class EntityConverter extends EntityConverterBase {
    */
   public function convert($value, $definition, $name, array $defaults) {
     $entity = parent::convert($value, $definition, $name, $defaults);
+    if (!\Drupal::currentUser()->hasPermission('access inline editing')) {
+      return $entity;
+    }
 
     // Use the Edit + tempstore version of an entity if it exist.
     $tempstore_entity = $this->editPlusTempstoreRepository->get($entity);
-    if ($tempstore_entity && $entity !== $tempstore_entity) {
-      $entity = $tempstore_entity;
-      // Flag that we have swapped this entity with a tempstore version.
-      edit_plus_active_tempstore_entities($entity);
+    if ($tempstore_entity) {
+      $tempstore_entity_array = $tempstore_entity->toArray();
+      $entity_array = $entity->toArray();
+      $difference = $this->recursiveArrayDiffAssoc($tempstore_entity_array, $entity_array);
+      if (!empty($difference)) {
+        $entity = $tempstore_entity;
+        // Flag that we have swapped this entity with a tempstore version.
+        edit_plus_active_tempstore_entities($entity);
+      }
     }
 
     return $entity;
   }
 
+  private function recursiveArrayDiffAssoc($array1, $array2) {
+    $difference = [];
+
+    foreach ($array1 as $key => $value) {
+      if (is_array($value) && isset($array2[$key]) && is_array($array2[$key])) {
+        $diff = $this->recursiveArrayDiffAssoc($value, $array2[$key]);
+        if (!empty($diff)) {
+          $difference[$key] = $diff;
+        }
+      } elseif (!array_key_exists($key, $array2) || $value !== $array2[$key]) {
+        $difference[$key] = $value;
+      }
+    }
+
+    return $difference;
+  }
+
 }
-- 
GitLab


From 8f875d7c94337aa945fd70880070461840fe1b86 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Mon, 16 Sep 2024 10:58:34 -0700
Subject: [PATCH 14/33] Return original response when modified field_widget_id
 is not present.

---
 assets/pencil-icon.svg                        | 16 ----------
 assets/text-toolbar.svg                       | 29 -------------------
 src/Form/ViewsFormMediaLibraryWidgetAlter.php |  2 +-
 src/Plugin/Tool/EditPlus.php                  |  2 +-
 4 files changed, 2 insertions(+), 47 deletions(-)
 delete mode 100644 assets/pencil-icon.svg
 delete mode 100644 assets/text-toolbar.svg

diff --git a/assets/pencil-icon.svg b/assets/pencil-icon.svg
deleted file mode 100644
index 818aa2b..0000000
--- a/assets/pencil-icon.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg id="Layer_7" data-name="Layer 7" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 34.78 43.96">
-  <defs>
-    <style>
-      .cls-1 {
-        fill: none;
-        stroke: #000;
-        stroke-miterlimit: 13.48;
-        stroke-width: 1.48px;
-      }
-    </style>
-  </defs>
-  <polyline class="cls-1" points="12.87 21.38 12.04 17 15.91 19.22"/>
-  <rect class="cls-1" x="15.96" y="19.53" width="3.6" height="10.97" transform="translate(-11.23 14.96) rotate(-35.5)"/>
-  <rect class="cls-1" x="19.9" y="29.25" width="3.6" height="2.57" transform="translate(-13.7 18.27) rotate(-35.5)"/>
-</svg>
\ No newline at end of file
diff --git a/assets/text-toolbar.svg b/assets/text-toolbar.svg
deleted file mode 100644
index 8288c30..0000000
--- a/assets/text-toolbar.svg
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg id="pencil" xmlns="http://www.w3.org/2000/svg" width="29.85" height="34.88" viewBox="0 0 19.85 25.88">
-  <defs>
-    <style>
-      .cls-1 {
-        stroke: #000;
-      }
-
-      .cls-1, .cls-2 {
-        stroke-miterlimit: 10;
-      }
-
-      .cls-2 {
-        fill: #fff;
-        stroke: #fff;
-      }
-    </style>
-  </defs>
-  <g id="white">
-    <rect class="cls-2" x="7.94" y="5.63" width="5.01" height="14.29" transform="translate(-5.54 8.68) rotate(-36.35)"/>
-    <polygon class="cls-2" points="7.42 4.92 3.84 7.55 2.83 2.46 7.42 4.92"/>
-    <rect class="cls-2" x="12.92" y="17.85" width="5" height="3.36" transform="translate(-8.57 12.94) rotate(-36.35)"/>
-  </g>
-  <g id="black">
-    <rect class="cls-1" x="8.6" y="6.18" width="3.07" height="12.47" transform="translate(-5.39 8.43) rotate(-36.35)"/>
-    <polygon class="cls-1" points="6.32 5.19 4.42 6.59 3.87 3.86 6.32 5.19"/>
-    <rect class="cls-1" x="13.84" y="18.82" width="3.04" height="1.47" transform="translate(-8.6 12.91) rotate(-36.35)"/>
-  </g>
-</svg>
diff --git a/src/Form/ViewsFormMediaLibraryWidgetAlter.php b/src/Form/ViewsFormMediaLibraryWidgetAlter.php
index cc39495..ee97bea 100644
--- a/src/Form/ViewsFormMediaLibraryWidgetAlter.php
+++ b/src/Form/ViewsFormMediaLibraryWidgetAlter.php
@@ -60,7 +60,7 @@ class ViewsFormMediaLibraryWidgetAlter {
 
     $parameters = $state->getOpenerParameters();
     if (empty($parameters['field_widget_id_and_block_uuid'])) {
-      throw new \InvalidArgumentException('field_widget_id_and_block_uuid parameter is missing.');
+      return $response;
     }
 
     $widget_id = $parameters['field_widget_id_and_block_uuid'];
diff --git a/src/Plugin/Tool/EditPlus.php b/src/Plugin/Tool/EditPlus.php
index 0e2dd3e..b87e4ec 100644
--- a/src/Plugin/Tool/EditPlus.php
+++ b/src/Plugin/Tool/EditPlus.php
@@ -28,7 +28,7 @@ final class EditPlus extends ToolPluginBase {
   public function getIconsPath(): array {
     $path = $this->extensionList->getPath('edit_plus');
     return [
-      'mouse_icon' => "/$path/assets/pencil-cursor.svg",
+      'mouse_icon' => "/$path/assets/text-mouse.svg",
       'toolbar_button_icons' => [
         'edit_plus' => "/$path/assets/pencil.svg",
       ],
-- 
GitLab


From 58f6f85f48f208dfb4e9c41056eba9ffaad5b473 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Tue, 17 Sep 2024 14:31:16 -0700
Subject: [PATCH 15/33] Disable editing on items that are currently being
 updated.

---
 assets/vendor/ckeditor5/editor-inline.js      |    2 +-
 css/edit-plus.css                             |   32 +
 js/edit-plus.js                               |    6 +
 js/edit_plus/editable-element.js              |    2 +-
 js/edit_plus/entity-form.js                   |   25 +-
 js/edit_plus/fields/field-plugin-base.js      |   16 +-
 .../edit_plus_lb/src/Form/UpdateBlockForm.php |    1 -
 package-lock.json                             | 1702 ++---------------
 package.json                                  |    2 +-
 src/Form/InlineEntityFormAlter.php            |    1 -
 yarn.lock                                     |  921 ++-------
 11 files changed, 439 insertions(+), 2271 deletions(-)

diff --git a/assets/vendor/ckeditor5/editor-inline.js b/assets/vendor/ckeditor5/editor-inline.js
index 8d28d50..cc9e4ad 100644
--- a/assets/vendor/ckeditor5/editor-inline.js
+++ b/assets/vendor/ckeditor5/editor-inline.js
@@ -1,4 +1,4 @@
 /*!
  * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
  * For licensing, see LICENSE.md.
- */(()=>{var t={782:(t,e,o)=>{t.exports=o(237)("./src/core.js")},783:(t,e,o)=>{t.exports=o(237)("./src/engine.js")},311:(t,e,o)=>{t.exports=o(237)("./src/ui.js")},584:(t,e,o)=>{t.exports=o(237)("./src/utils.js")},237:t=>{"use strict";t.exports=CKEditor5.dll}},e={};function o(i){var r=e[i];if(void 0!==r)return r.exports;var n=e[i]={exports:{}};return t[i](n,n.exports,o),n.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,{InlineEditor:()=>C});var t=o(782),e=o(584),r=o(311),n=o(783);class s extends r.EditorUI{constructor(t,e){super(t),this.view=e,this._toolbarConfig=(0,r.normalizeToolbarConfig)(t.config.get("toolbar"))}get element(){return this.view.editable.element}init(){const t=this.editor,e=this.view,o=t.editing.view,i=e.editable,r=o.document.getRoot();i.name=r.rootName,e.render();const n=i.element;this.setEditableElement(i.name,n),i.bind("isFocused").to(this.focusTracker),o.attachDomRoot(n),this._initPlaceholder(),this._initToolbar(),this.fire("ready")}destroy(){super.destroy();const t=this.view;this.editor.editing.view.detachDomRoot(t.editable.name),t.destroy()}_initToolbar(){const t=this.editor,e=this.view,o=e.editable.element,i=e.toolbar;e.panel.bind("isVisible").to(this.focusTracker,"isFocused"),e.bind("viewportTopOffset").to(this,"viewportOffset",(({top:t})=>t||0)),e.listenTo(t.ui,"update",(()=>{e.panel.isVisible&&e.panel.pin({target:o,positions:e.panelPositions})})),i.fillFromConfig(this._toolbarConfig,this.componentFactory),this.addToolbar(i)}_initPlaceholder(){const t=this.editor,e=t.editing.view,o=e.document.getRoot(),i=t.config.get("placeholder");if(i){const t="string"==typeof i?i:i[o.rootName];t&&(o.placeholder=t)}(0,n.enablePlaceholder)({view:e,element:o,isDirectHost:!1,keepOnFocus:!0})}}const l=(0,e.toUnit)("px");class a extends r.EditorUIView{constructor(t,e,o,i={}){super(t);const n=t.t;this.toolbar=new r.ToolbarView(t,{shouldGroupWhenFull:i.shouldToolbarGroupWhenFull,isFloating:!0}),this.set("viewportTopOffset",0),this.panel=new r.BalloonPanelView(t),this.panelPositions=this._getPanelPositions(),this.panel.extendTemplate({attributes:{class:"ck-toolbar-container"}}),this.editable=new r.InlineEditableUIView(t,e,o,{label:t=>n("Rich Text Editor. Editing area: %0",t.name)}),this._resizeObserver=null}render(){super.render(),this.body.add(this.panel),this.registerChild(this.editable),this.panel.content.add(this.toolbar);if(this.toolbar.options.shouldGroupWhenFull){const t=this.editable.element;this._resizeObserver=new e.ResizeObserver(t,(()=>{this.toolbar.maxWidth=l(new e.Rect(t).width)}))}}destroy(){super.destroy(),this._resizeObserver&&this._resizeObserver.destroy()}_getPanelPositionTop(t,e){let o;return o=t.top>e.height+this.viewportTopOffset?t.top-e.height:t.bottom>e.height+this.viewportTopOffset+50?this.viewportTopOffset:t.bottom,o}_getPanelPositions(){const t=[(t,e)=>({top:this._getPanelPositionTop(t,e),left:t.left,name:"toolbar_west",config:{withArrow:!1}}),(t,e)=>({top:this._getPanelPositionTop(t,e),left:t.left+t.width-e.width,name:"toolbar_east",config:{withArrow:!1}})];return"ltr"===this.locale.uiLanguageDirection?t:t.reverse()}}const c=function(t){return null!=t&&"object"==typeof t};const d="object"==typeof global&&global&&global.Object===Object&&global;var h="object"==typeof self&&self&&self.Object===Object&&self;const u=(d||h||Function("return this")()).Symbol;var p=Object.prototype,b=p.hasOwnProperty,f=p.toString,g=u?u.toStringTag:void 0;const w=function(t){var e=b.call(t,g),o=t[g];try{t[g]=void 0;var i=!0}catch(t){}var r=f.call(t);return i&&(e?t[g]=o:delete t[g]),r};var v=Object.prototype.toString;const m=function(t){return v.call(t)};var y=u?u.toStringTag:void 0;const O=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":y&&y in Object(t)?w(t):m(t)};const T=function(t,e){return function(o){return t(e(o))}}(Object.getPrototypeOf,Object);var j=Function.prototype,E=Object.prototype,P=j.toString,_=E.hasOwnProperty,x=P.call(Object);const F=function(t){if(!c(t)||"[object Object]"!=O(t))return!1;var e=T(t);if(null===e)return!0;var o=_.call(e,"constructor")&&e.constructor;return"function"==typeof o&&o instanceof o&&P.call(o)==x};const S=function(t){return c(t)&&1===t.nodeType&&!F(t)};class C extends((0,t.ElementApiMixin)(t.Editor)){constructor(o,i={}){if(!D(o)&&void 0!==i.initialData)throw new e.CKEditorError("editor-create-initial-data",null);super(i),void 0===this.config.get("initialData")&&this.config.set("initialData",function(t){return D(t)?(0,e.getDataFromElement)(t):t}(o)),this.model.document.createRoot(),D(o)&&(this.sourceElement=o,(0,t.secureSourceElement)(this,o));const r=!this.config.get("toolbar.shouldNotGroupWhenFull"),n=new a(this.locale,this.editing.view,this.sourceElement,{shouldToolbarGroupWhenFull:r});this.ui=new s(this,n),(0,t.attachToForm)(this)}destroy(){const t=this.getData();return this.ui.destroy(),super.destroy().then((()=>{this.sourceElement&&this.updateSourceElement(t)}))}static create(t,o={}){return new Promise((i=>{if(D(t)&&"TEXTAREA"===t.tagName)throw new e.CKEditorError("editor-wrong-element",null);const r=new this(t,o);i(r.initPlugins().then((()=>r.ui.init())).then((()=>r.data.init(r.config.get("initialData")))).then((()=>r.fire("ready"))).then((()=>r)))}))}}function D(t){return S(t)}})(),(window.CKEditor5=window.CKEditor5||{}).editorInline=i})();
\ No newline at end of file
+ */(()=>{var t={782:(t,e,o)=>{t.exports=o(237)("./src/core.js")},783:(t,e,o)=>{t.exports=o(237)("./src/engine.js")},311:(t,e,o)=>{t.exports=o(237)("./src/ui.js")},584:(t,e,o)=>{t.exports=o(237)("./src/utils.js")},602:(t,e,o)=>{t.exports=o(237)("./src/watchdog.js")},237:t=>{"use strict";t.exports=CKEditor5.dll}},e={};function o(i){var r=e[i];if(void 0!==r)return r.exports;var n=e[i]={exports:{}};return t[i](n,n.exports,o),n.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,{InlineEditor:()=>W});var t=o(782),e=o(584),r=o(602),n=o(311),s=o(783);class l extends n.EditorUI{constructor(t,e){super(t),this.view=e,this._toolbarConfig=(0,n.normalizeToolbarConfig)(t.config.get("toolbar"))}get element(){return this.view.editable.element}init(){const t=this.editor,e=this.view,o=t.editing.view,i=e.editable,r=o.document.getRoot();i.name=r.rootName,e.render();const n=i.element;this.setEditableElement(i.name,n),i.bind("isFocused").to(this.focusTracker),o.attachDomRoot(n),this._initPlaceholder(),this._initToolbar(),this.fire("ready")}destroy(){super.destroy();const t=this.view;this.editor.editing.view.detachDomRoot(t.editable.name),t.destroy()}_initToolbar(){const t=this.editor,e=this.view,o=e.editable.element,i=e.toolbar;e.panel.bind("isVisible").to(this.focusTracker,"isFocused"),e.bind("viewportTopOffset").to(this,"viewportOffset",(({top:t})=>t||0)),e.listenTo(t.ui,"update",(()=>{e.panel.isVisible&&e.panel.pin({target:o,positions:e.panelPositions})})),i.fillFromConfig(this._toolbarConfig,this.componentFactory),this.addToolbar(i)}_initPlaceholder(){const t=this.editor,e=t.editing.view,o=e.document.getRoot(),i=t.config.get("placeholder");if(i){const t="string"==typeof i?i:i[o.rootName];t&&(o.placeholder=t)}(0,s.enablePlaceholder)({view:e,element:o,isDirectHost:!1,keepOnFocus:!0})}}const a=(0,e.toUnit)("px");class c extends n.EditorUIView{constructor(t,e,o,i={}){super(t);const r=t.t;this.toolbar=new n.ToolbarView(t,{shouldGroupWhenFull:i.shouldToolbarGroupWhenFull,isFloating:!0}),this.set("viewportTopOffset",0),this.panel=new n.BalloonPanelView(t),this.panelPositions=this._getPanelPositions(),this.panel.extendTemplate({attributes:{class:"ck-toolbar-container"}}),this.editable=new n.InlineEditableUIView(t,e,o,{label:t=>r("Rich Text Editor. Editing area: %0",t.name)}),this._resizeObserver=null}render(){super.render(),this.body.add(this.panel),this.registerChild(this.editable),this.panel.content.add(this.toolbar);if(this.toolbar.options.shouldGroupWhenFull){const t=this.editable.element;this._resizeObserver=new e.ResizeObserver(t,(()=>{this.toolbar.maxWidth=a(new e.Rect(t).width)}))}}destroy(){super.destroy(),this._resizeObserver&&this._resizeObserver.destroy()}_getPanelPositionTop(t,e){let o;return o=t.top>e.height+this.viewportTopOffset?t.top-e.height:t.bottom>e.height+this.viewportTopOffset+50?this.viewportTopOffset:t.bottom,o}_getPanelPositions(){const t=[(t,e)=>({top:this._getPanelPositionTop(t,e),left:t.left,name:"toolbar_west",config:{withArrow:!1}}),(t,e)=>({top:this._getPanelPositionTop(t,e),left:t.left+t.width-e.width,name:"toolbar_east",config:{withArrow:!1}})];return"ltr"===this.locale.uiLanguageDirection?t:t.reverse()}}const d=function(t){return null!=t&&"object"==typeof t};const h="object"==typeof global&&global&&global.Object===Object&&global;var u="object"==typeof self&&self&&self.Object===Object&&self;const p=(h||u||Function("return this")()).Symbol;var b=Object.prototype,f=b.hasOwnProperty,g=b.toString,w=p?p.toStringTag:void 0;const v=function(t){var e=f.call(t,w),o=t[w];try{t[w]=void 0;var i=!0}catch(t){}var r=g.call(t);return i&&(e?t[w]=o:delete t[w]),r};var m=Object.prototype.toString;const y=function(t){return m.call(t)};var O=p?p.toStringTag:void 0;const T=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":O&&O in Object(t)?v(t):y(t)};const j=function(t,e){return function(o){return t(e(o))}}(Object.getPrototypeOf,Object);var E=Function.prototype,P=Object.prototype,x=E.toString,_=P.hasOwnProperty,F=x.call(Object);const C=function(t){if(!d(t)||"[object Object]"!=T(t))return!1;var e=j(t);if(null===e)return!0;var o=_.call(e,"constructor")&&e.constructor;return"function"==typeof o&&o instanceof o&&x.call(o)==F};const S=function(t){return d(t)&&1===t.nodeType&&!C(t)};class D extends((0,t.ElementApiMixin)(t.Editor)){constructor(o,i={}){if(!R(o)&&void 0!==i.initialData)throw new e.CKEditorError("editor-create-initial-data",null);super(i),void 0===this.config.get("initialData")&&this.config.set("initialData",function(t){return R(t)?(0,e.getDataFromElement)(t):t}(o)),this.model.document.createRoot(),R(o)&&(this.sourceElement=o,(0,t.secureSourceElement)(this,o));const r=!this.config.get("toolbar.shouldNotGroupWhenFull"),n=new c(this.locale,this.editing.view,this.sourceElement,{shouldToolbarGroupWhenFull:r});this.ui=new l(this,n),(0,t.attachToForm)(this)}destroy(){const t=this.getData();return this.ui.destroy(),super.destroy().then((()=>{this.sourceElement&&this.updateSourceElement(t)}))}static create(t,o={}){return new Promise((i=>{if(R(t)&&"TEXTAREA"===t.tagName)throw new e.CKEditorError("editor-wrong-element",null);const r=new this(t,o);i(r.initPlugins().then((()=>r.ui.init())).then((()=>r.data.init(r.config.get("initialData")))).then((()=>r.fire("ready"))).then((()=>r)))}))}}D.Context=t.Context,D.EditorWatchdog=r.EditorWatchdog,D.ContextWatchdog=r.ContextWatchdog;const W=D;function R(t){return S(t)}})(),(window.CKEditor5=window.CKEditor5||{}).editorInline=i})();
\ No newline at end of file
diff --git a/css/edit-plus.css b/css/edit-plus.css
index 5dbea2d..f06a29c 100644
--- a/css/edit-plus.css
+++ b/css/edit-plus.css
@@ -39,3 +39,35 @@ div.edit-plus-hidden {
 .block .button.js-hide {
   display: none;
 }
+
+[data-edit-plus-id] {
+
+  &:has(> .ajax-progress) {
+    position: relative;
+  }
+
+  .ajax-progress {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    background-color: rgba(0, 0, 0, 0);
+    transition: background-color .15s ease-out;
+    color: #fff;
+    font-size: 1rem;
+    font-weight: 300;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+
+    &.background-fade-in {
+      background-color: rgba(0, 0, 0, .9);
+    }
+
+    .throbber,
+    .message {
+      display: block;
+    }
+  }
+}
diff --git a/js/edit-plus.js b/js/edit-plus.js
index dee8c04..acdabd2 100644
--- a/js/edit-plus.js
+++ b/js/edit-plus.js
@@ -54,7 +54,13 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
 
     const EditableElement = new editableElement.EditableElement(fieldValue.dataset.editPlusId);
 
+    // Don't edit items that are currently being updated.
+    if (EditableElement.getPageElementHandle().classList.contains('disabled-updating')) {
+      return;
+    }
+
     entityForm.getForm(EditableElement).then((response, status) => {
+      // Set the widget now that the form is loaded.
       EditableElement.setWidget();
       Drupal.EditPlus.FieldPluginManager.getPlugin(EditableElement).edit(EditableElement);
     });
diff --git a/js/edit_plus/editable-element.js b/js/edit_plus/editable-element.js
index 8f768f3..4942ae5 100644
--- a/js/edit_plus/editable-element.js
+++ b/js/edit_plus/editable-element.js
@@ -91,7 +91,7 @@ export class EditableElement {
    *   wrapper into the page for editing.
    */
   getHandleType() {
-    return this.getFormItemWrapper().dataset.editPlusHandle ?? 'form_item';
+    return this.getFormItemWrapper()?.dataset.editPlusHandle ?? 'form_item';
   }
 
   /**
diff --git a/js/edit_plus/entity-form.js b/js/edit_plus/entity-form.js
index 1bcd373..1c161ac 100644
--- a/js/edit_plus/entity-form.js
+++ b/js/edit_plus/entity-form.js
@@ -185,21 +185,40 @@ export const updateTempstore = (EditableElement, isEmpty, form = null) => {
     form.querySelector('#empty-field').value = EditableElement.info.fieldName;
   }
 
-  // Update the hidden view mode input.
+  // Update the hidden view mode input in order to persist the view mode across
+  // multiple form submissions as it could change during one of them.
   let viewMode;
   if (EditableElement) {
     // I think we can standardize on getting the view mode from the form > entity
     // wrapper relationship, but we might as well get it from EditableElement
     // when it's available as it's a tiny bit faster.
     viewMode = EditableElement.info.viewMode;
+
+    // Add an AJAX throbber to indicate the item is being updated.
+    const pageElementHandle = EditableElement.getPageElementHandle();
+    const throbber = Drupal.theme.ajaxProgressThrobber(Drupal.t('Updating...'));
+    pageElementHandle.insertAdjacentHTML('beforeend', throbber);
+    setTimeout(() => {
+      document.querySelector('[data-edit-plus-id] .ajax-progress').classList.add('background-fade-in');
+    }, 50);
+    // Disable the item while it's being updated.
+    const disable = element => {
+      element.classList.add('disabled-updating');
+    };
+    if (pageElementHandle.classList.contains('edit-plus-field-value')) {
+      disable(pageElementHandle);
+    }
+    pageElementHandle.querySelector('.edit-plus-field-value')?.forEach(disable);
+
   } else {
     // EditableElement won't be available when submitting the form via EditPlusEntityFormAutoSave.
-    const entityWrapper = document.querySelector('[data-toolbar-plus-entity-wrapper^="' + form.closest('.edit-plus-form').dataset.editPlusFormId + '"]')
+    const entityWrapper = document.querySelector('[data-toolbar-plus-entity-wrapper^="' + form.closest('.edit-plus-form').dataset.editPlusFormId + '"]');
     const info = utilities.parseEntityWrapperId(entityWrapper.dataset.toolbarPlusEntityWrapper);
     viewMode = info.viewMode;
   }
   form.querySelector('.edit-plus-view-mode').value = viewMode;
 
+
   // Click the update button (formerly the save submit).
   const updateButton = form.querySelector('.edit-plus-update-button');
   jQuery(updateButton).mousedown();
@@ -208,7 +227,7 @@ export const updateTempstore = (EditableElement, isEmpty, form = null) => {
 
 jQuery.fn.editPlusIsDoneUpdating = () => {
   editPlusIsUpdating = false;
-}
+};
 
 (($, Drupal, once) => {
 
diff --git a/js/edit_plus/fields/field-plugin-base.js b/js/edit_plus/fields/field-plugin-base.js
index ce2cf49..ad88d86 100644
--- a/js/edit_plus/fields/field-plugin-base.js
+++ b/js/edit_plus/fields/field-plugin-base.js
@@ -97,12 +97,16 @@ export class FieldPluginBase {
       }
     }
     if (!remainFocused) {
-      const fieldValue = e.target.closest('.edit-plus-field-value');
-      if (fieldValue) {
-        // We lost focus when clicking another editable element. Only update the
-        // rendered page with the last changed element.
-        Drupal.EditPlus.onlyUpdateElement = Drupal.EditPlus.Focused.editableElement;
-      }
+      // Only update the page with the item that was just changed.
+      Drupal.EditPlus.onlyUpdateElement = Drupal.EditPlus.Focused.editableElement;
+
+      // @todo Can we just always only update the thing that was changed?
+      // const fieldValue = e.target.closest('.edit-plus-field-value');
+      // if (fieldValue) {
+      //   // We lost focus when clicking another editable element. Only update the
+      //   // rendered page with the last changed element.
+      //   Drupal.EditPlus.onlyUpdateElement = Drupal.EditPlus.Focused.editableElement;
+      // }
 
       plugin.blur();
       document.querySelectorAll('.edit-plus-focused').forEach(element => {
diff --git a/modules/edit_plus_lb/src/Form/UpdateBlockForm.php b/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
index bd7fe4f..eb4954c 100644
--- a/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
+++ b/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
@@ -88,7 +88,6 @@ class UpdateBlockForm extends UpdateBlockFormBase implements EntityFormInterface
     $form_state->set('section_storage', $section_storage);
 
     $form['actions']['submit']['#attributes']['class'][] = 'edit-plus-update-button';
-    $form['actions']['submit']['#ajax']['progress'] = ['type' => 'fullscreen'];
     $form['actions']['submit']['#attributes']['class'][] = 'edit-plus-hidden';
 
     $form['settings']['block_form']['#process'][] = [$this, 'processBlockForm'];
diff --git a/package-lock.json b/package-lock.json
index a9458b2..979e883 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,676 +5,107 @@
     "packages": {
         "": {
             "devDependencies": {
-                "@ckeditor/ckeditor5-editor-inline": "~42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-adapter-ckfinder": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-adapter-ckfinder/-/ckeditor5-adapter-ckfinder-42.0.2.tgz",
-            "integrity": "sha512-nX624WYyyJh6BGGy7jNOlEyf+Kv95VWHKlqn39HLTLKlONBp3zBhAtN9rd0gqU5EM6FgPQ+RjOtQinuto0B6oQ==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-upload": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-alignment": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-alignment/-/ckeditor5-alignment-42.0.2.tgz",
-            "integrity": "sha512-g6I0f5Ko7tckHrKYyZhNQL3dGHTcMbjypIfEkk3SAv68X4bDKLImVUJ1L6y0aZnGNoI40cMr0byEyln5rOq67Q==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-autoformat": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autoformat/-/ckeditor5-autoformat-42.0.2.tgz",
-            "integrity": "sha512-tnMdNc8VJ4y4wqbkSAbBGRiUukByOo1nBqyvzYS+SZ2Wzo67OmzKybvqz60PFYIbPAQJa0/uFkvgd55c+VTaqg==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-autosave": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autosave/-/ckeditor5-autosave-42.0.2.tgz",
-            "integrity": "sha512-QIsftrJ6LjJrmUTDfJYpBKy9DJ79ltt2pMHtb8DhoyugGZUup40pFvMrt/4/UuQRm64jS/IjhwWXkSMg4PejJw==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-basic-styles": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-basic-styles/-/ckeditor5-basic-styles-42.0.2.tgz",
-            "integrity": "sha512-LT0Kk1K30z/YhI48QBDa69tjU1G2ljSKi5pU5pfiSBLhMl1ShLmXIAy6cEHnijHS0mte8FGwhiGXmNB/jAZ7Iw==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-block-quote": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-block-quote/-/ckeditor5-block-quote-42.0.2.tgz",
-            "integrity": "sha512-xfX+tdAhn7WPHNNZR5Wkjl+OnmbNlEOVVZCL2iAjfswf4r3CglLnJOa529FO+4MyNcwkP+joQ3iVBclZNbETLw==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-enter": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-ckbox": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ckbox/-/ckeditor5-ckbox-42.0.2.tgz",
-            "integrity": "sha512-RvCUphlhrTuGBy78kEOFJvdvmP3o7ajibubOOpVfUMz1V8BbTmmx1+XaveCDxznkwiCLUwqZplWZnpPoEABj2w==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-upload": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "blurhash": "2.0.5",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-ckfinder": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ckfinder/-/ckeditor5-ckfinder-42.0.2.tgz",
-            "integrity": "sha512-3lkMF+9Z3R1OUfwZJdORlRDgPSyR9Be57zgizpevpKTenxrZ+UU33ib/kvK8LXVDOzz3qp7UyCucLfY1KNXCzA==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
+                "@ckeditor/ckeditor5-editor-inline": "~41.3.1"
             }
         },
         "node_modules/@ckeditor/ckeditor5-clipboard": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-42.0.2.tgz",
-            "integrity": "sha512-x76SjAhaguwVQtJSgz62q96RsJsw0eSM7ZnuUqLjMMzO+hq2hAj7ZIJNPcA46ZyDR6LDQzH760IumSz0xlHn9w==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-41.3.1.tgz",
+            "integrity": "sha512-6S7tq6FlnHYZmPACeqdf135Jx2bTKHVY8mHQ+CHC8ZZu0XVm62vVeeSLS2IcdtYmHjf4ced1G7suTUBHlfBCLw==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-cloud-services": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-cloud-services/-/ckeditor5-cloud-services-42.0.2.tgz",
-            "integrity": "sha512-oNdtgD/suEh5nAndXsjik8HgRDk095EGxkmrMO+Z3gbOit28fvTDL6bbUOQvenoNNWa7RXLZMbfyiTMuNH+X8Q==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-code-block": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-code-block/-/ckeditor5-code-block-42.0.2.tgz",
-            "integrity": "sha512-NFGn+350VS6/UNhHm9CurOLm3ZiXFUCO/SgKRILPKZ82Wh2GQqocs5O3yvvo1WQ9jA2DEwjfN0TgOpwgVOZQPQ==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-enter": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-engine": "41.3.1",
+                "@ckeditor/ckeditor5-ui": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1",
+                "@ckeditor/ckeditor5-widget": "41.3.1",
                 "lodash-es": "4.17.21"
             }
         },
         "node_modules/@ckeditor/ckeditor5-core": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-42.0.2.tgz",
-            "integrity": "sha512-LkNx1Qpk/gwh0wYkl4FdZfi1N2G5Gmp026sVp301boyE9sSVeR3YxcSdKXfsr2HII+7EdJHxMswTvnd/L+IdSg==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-watchdog": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-easy-image": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-easy-image/-/ckeditor5-easy-image-42.0.2.tgz",
-            "integrity": "sha512-JYVpX6lRVRve8roROx5y6nsixLXLuVwIokBLoo+usS313xeeZvjoLrxGTeRuyyVbK3BFPE+zqyXsgqGs1Q0stg==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-upload": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-editor-balloon": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-balloon/-/ckeditor5-editor-balloon-42.0.2.tgz",
-            "integrity": "sha512-NXTVQ3aBW8OirKgv8PJvjSDDbl39JGlnS/W+/LRwUlOgHVVWHVSMMqY52AhP90TzP6xfbFYBYX8n13EB6o/4Bw==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-41.3.1.tgz",
+            "integrity": "sha512-h+PgPtCpS2vjO3HbKMYtddRPW+B3AJx9qpixmHJnUZMiFCmRjUZjXATjpi3j+kSQISs4L2Yghq+lsAQxyGHb+A==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-editor-classic": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-classic/-/ckeditor5-editor-classic-42.0.2.tgz",
-            "integrity": "sha512-K9+154AP/OpxDn6702772QCiT830lAQXsiUty1Z35MM3hVS5quwkuxS6V0NjKxx0AcqUmmgdXoFxx6v4mj3R7g==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-editor-decoupled": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-decoupled/-/ckeditor5-editor-decoupled-42.0.2.tgz",
-            "integrity": "sha512-ANhlpcZXV+nZl/f9o+wS5vqc+Va5K4LnYA0F/pJNTNlighVCa1nGQX11tRGm48vItpNlgQxty+p86NHa+7YrLw==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1",
                 "lodash-es": "4.17.21"
             }
         },
         "node_modules/@ckeditor/ckeditor5-editor-inline": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-inline/-/ckeditor5-editor-inline-42.0.2.tgz",
-            "integrity": "sha512-gWngpGE/6JDCyKpKTX7iIgFaxrDPzocZt56p1JmBJCNpVQb4sGoZs94uUg7rxlVo8t3PDH+foL49gSdBKYS9uw==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-editor-multi-root": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-multi-root/-/ckeditor5-editor-multi-root-42.0.2.tgz",
-            "integrity": "sha512-1Cv4WGB75KoWZWewCOnHP4s4HGFXKt3BajvDkN8LXS6CtaIPDkH18okY/ivH/Idhu1pT9k2bjzCfR7W4EhtRJg==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-inline/-/ckeditor5-editor-inline-41.3.1.tgz",
+            "integrity": "sha512-bAhs57qbeGT907yFsUUxdujtrNlmOTJK4DrBCsxoKSoSo8fcG4D05g/I4ehQp3A1CFYsF2Wkx58TtI/fwWRVbQ==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
+                "ckeditor5": "41.3.1",
                 "lodash-es": "4.17.21"
             }
         },
         "node_modules/@ckeditor/ckeditor5-engine": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-42.0.2.tgz",
-            "integrity": "sha512-mI4+X6Z0ihnyAKzka5RjoUgZoaRDckMniN8LLYNum3ewz+KWIVjtHn6NBrqEqw24BpwYfSVEPL/NdgA6xl93Jw==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-41.3.1.tgz",
+            "integrity": "sha512-Me4cnkCrknDH50db/jPczuhgzaxUhHbkh2gv8N8Ypken9ZnOPvMD9W1gCFFTLaxikpPmBQwk3u1BSjOKk3r6kw==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "41.3.1",
                 "lodash-es": "4.17.21"
             }
         },
         "node_modules/@ckeditor/ckeditor5-enter": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-42.0.2.tgz",
-            "integrity": "sha512-pzVXQPdBgskiqVpCG/yxliuEXPECCI3GJ/OF5wXs2GQ04IcqBz5FsazUtSLS5nnA4e3YpcdzzEC0Kn1ASdl7QQ==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-essentials": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-essentials/-/ckeditor5-essentials-42.0.2.tgz",
-            "integrity": "sha512-4qhW/7zm69KHnotKEs05YB6YTD6WB6QWJ6U44V6dFGJUUUmYN1fOt9ri6lU8snUVhJrU0C9IuGpVkb8Aby79GQ==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-41.3.1.tgz",
+            "integrity": "sha512-iwhvJpfsutqcv/bf8QPMKhMolb7GtShaOT+UIDW3OXjMZaBKZOTyR8OceijwgBmZeillTaXQq9y2e9lbJd46xg==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-enter": "42.0.2",
-                "@ckeditor/ckeditor5-select-all": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-undo": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-find-and-replace": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-find-and-replace/-/ckeditor5-find-and-replace-42.0.2.tgz",
-            "integrity": "sha512-9Fc5nKUhDtivHxGoY5nEvwjqUyvMwcNs1Xo6nt9aXeG0gd4mrCdUQaQfRIlcycLmeVD1MgKfWh7sOv+EtuYFRA==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-font": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-font/-/ckeditor5-font-42.0.2.tgz",
-            "integrity": "sha512-Soj1auf82Zz6y56qKf6nV6RSjNPENZm9vpkJ9jhyQ4pMh6YvQ7EkzbOwPCoskXm+ab8EAuH+bjS0n5lewN5i7Q==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-heading": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-heading/-/ckeditor5-heading-42.0.2.tgz",
-            "integrity": "sha512-1lwxsxzJRikSerwhH1By9FlAO2EQhcrt3xnpxBFME3pS2Y6tbkHj81W5Lu2cf+0ew5Bzcp5uqTvaArRtVssY1A==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-paragraph": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-highlight": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-highlight/-/ckeditor5-highlight-42.0.2.tgz",
-            "integrity": "sha512-I/qVqC1YS6Hfg1dZjP665NU2fIx5Dk4Rjq2ku7yxQrsmG+rle2xrEzXF1BsaBeK6ko+fX7JaP86dTvywnnOeaw==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-horizontal-line": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-horizontal-line/-/ckeditor5-horizontal-line-42.0.2.tgz",
-            "integrity": "sha512-zXnK2k5F5lhbLVwHzyURPMRGc8pc1YPz8fYXmz1pf/JG/EgXGGuUlczkpzegBUb9MctFgZbs09xIkTkVBQZmNw==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-html-embed": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-html-embed/-/ckeditor5-html-embed-42.0.2.tgz",
-            "integrity": "sha512-aqCV9vQJd6KiYsTEW6UlWtyMTZgXI2oHK7/1p8WUagabHU1ZFT+jkExC8QG9n0M76Sq9TIynqBlfl4OOijT6NQ==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-html-support": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-html-support/-/ckeditor5-html-support-42.0.2.tgz",
-            "integrity": "sha512-z+Tg/jOf9+wzCo/NywkuHPGfOnKHfSr0hvkGjrq8b2OU9B1nJI34VTjJWSFH5NfLpn3tZo2dy3EcaoN9B7rSHA==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-enter": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-image": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-image/-/ckeditor5-image-42.0.2.tgz",
-            "integrity": "sha512-RH1r10rsnEFSBNBXe3d02J6JDvoLKxwz/KCvC/EoOR4UEKDe0FNodt3+VZrb0JNqkBUIxqdtvEobXb6YmGQaDQ==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-undo": "42.0.2",
-                "@ckeditor/ckeditor5-upload": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-indent": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-indent/-/ckeditor5-indent-42.0.2.tgz",
-            "integrity": "sha512-qXVXqvflW8kKa7odjiSTrQtj75C5opmnGUyrM+37f7CC8OmrcjXJ5GgrFnKwHyny9YHtvQyyN+GCuzuir6a9eA==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-language": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-language/-/ckeditor5-language-42.0.2.tgz",
-            "integrity": "sha512-s0pMdNxuE+kBCFiop5Lgv/UsYAYLKCENesMXVIRrxI73GRjwJXIq5f/5a7xwvfmH3/TQT5GMrfNmf5EeYo5NHA==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-link": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-link/-/ckeditor5-link-42.0.2.tgz",
-            "integrity": "sha512-KySX11v1RyimZyc4u3AF6a/bEvA3gQg/krRsrzBbMIadtC1WN/C7w7XzjmYvx8Ui0SsH/ChBu16SxmRKO4HuTA==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-list": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-list/-/ckeditor5-list-42.0.2.tgz",
-            "integrity": "sha512-NTNDb01QDyjDZis8nyOsvgSNwy6YniulGDZdyeulhmFy6zyHG0GFeYA0kAyW6/bnniWyW9cpfUrAK9KTLuql4A==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-enter": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-markdown-gfm": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-markdown-gfm/-/ckeditor5-markdown-gfm-42.0.2.tgz",
-            "integrity": "sha512-mh81YHQqVF0ZVSgd7hbO3EzuM78zIhwwZiiVsJ68e4aCfpYjc3Ni1NpyORj+tian743PmFr7WAUqIePdNPmQEg==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "marked": "4.0.12",
-                "turndown": "7.2.0",
-                "turndown-plugin-gfm": "1.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-media-embed": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-media-embed/-/ckeditor5-media-embed-42.0.2.tgz",
-            "integrity": "sha512-iXGcfgOm0IWa600ln5YeSssg7Sew6Lf1z9ziTxsQsmforPIqXgZQEvdLoo0tABddSRQZI+yQZnRnwrus9sZXIA==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-undo": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-mention": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-mention/-/ckeditor5-mention-42.0.2.tgz",
-            "integrity": "sha512-81MYULfB7bHDb5Y7saIZMkNVG1BJV/ir5BwIDuuXwGXLNVX++uMTK4ryAItYToiSFN8/NBms7JFXPrRhL/zbOw==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-minimap": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-minimap/-/ckeditor5-minimap-42.0.2.tgz",
-            "integrity": "sha512-dOBT6bS/7tREFmpRCD4XwOEmoW4p7ZV1Pp3tA/KYQ++2BAgI/O/Yeww7nlhsKhal4r74v459hgihI/SnlfqBQA==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-page-break": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-page-break/-/ckeditor5-page-break-42.0.2.tgz",
-            "integrity": "sha512-h6Wb0fWsl4a0MyU8W3F4Yku/1CWnR6tQrcMapn0sHB9W/HAvHLQIJGdsYh+a1W6QzMIjpVAqjT4mxQ1rU86RkQ==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "ckeditor5": "42.0.2"
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-engine": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1"
             }
         },
         "node_modules/@ckeditor/ckeditor5-paragraph": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-42.0.2.tgz",
-            "integrity": "sha512-feI7Rw76uPbPmoFeVEPpKdPTOjdlccpWabhfrimgT08rECLa7ErFw2oRZVmnx5+kjX+NAUeD9kaUZUUkNNP0wg==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-paste-from-office": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paste-from-office/-/ckeditor5-paste-from-office-42.0.2.tgz",
-            "integrity": "sha512-9K54E44rEjvLqWKRRHeifOlb1bICKzzX8gOv/i90sFQfMeQphA6qEn3WJZNQY4NY9Uwhu3kF/gh3/dqlcBhsvw==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-remove-format": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-remove-format/-/ckeditor5-remove-format-42.0.2.tgz",
-            "integrity": "sha512-YIyKibU44Jt6P9qu3WGPjUUh/pb5dvexeE1XG6f5JNtVlZCy3sUI+BDytzqWI68/coOHBKYkKSDOEQdzw83PdA==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-41.3.1.tgz",
+            "integrity": "sha512-weRPLyO/1Z8PpU9+lET4gYgJ8adDuCjYiREup81URSuS1DDQ8vb3D29xA+4Ov7lwg8BaNAMCpTBdp07GHHzv6w==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-restricted-editing": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-restricted-editing/-/ckeditor5-restricted-editing-42.0.2.tgz",
-            "integrity": "sha512-tfnEE6ieR2UhjZ9zoDNfXIMAMy2FWoajASKffdtpTMBjkVKzM+isg8j0hEkWgiQqCsJYVWt0314nPZrm5EUIfA==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-ui": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1"
             }
         },
         "node_modules/@ckeditor/ckeditor5-select-all": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-42.0.2.tgz",
-            "integrity": "sha512-eqLhxmsxDQ8s+Op4f0OoXbN9vwz0hekE1HxsClXIsqwhjsO2o/HYcyhIzR9lPgmi4bVf8uy8T9oyWQNRLv4S9w==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-show-blocks": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-show-blocks/-/ckeditor5-show-blocks-42.0.2.tgz",
-            "integrity": "sha512-CFYJN3gyiWwJ1mDonzIktRL/A+WONZuyCptELqlU51RRCwbG7eSMtu2Eyd+Q463zYbOKZcdr5uNvlWuRpSsalw==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-source-editing": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-source-editing/-/ckeditor5-source-editing-42.0.2.tgz",
-            "integrity": "sha512-lo/ZmBeAoWu9j0qfuUVIpc2QzZmcrYZ2enloz2mL22DCn3eP8IstE7gSmZlQ/DQxcPC5Sf2uC0l9IurBAP9+pg==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-theme-lark": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-special-characters": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-special-characters/-/ckeditor5-special-characters-42.0.2.tgz",
-            "integrity": "sha512-B2E9thXW0Ej1istiResH6987g+REnX18aoxW4uXG+PHDrYWjsV4fClEnjWdkO/O0A3yOoNc4LYAbGSo7z0g/1g==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-style": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-style/-/ckeditor5-style-42.0.2.tgz",
-            "integrity": "sha512-vq1GSeOtZm00W4FC6MgqukJbdDE394Sh7ID6634gKmdknbxOBvNcF0XUdAu+kWtJzTjYVrC4+oPYpS5C+odidQ==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-table": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-table/-/ckeditor5-table-42.0.2.tgz",
-            "integrity": "sha512-fFMXbQCa7UR4aAmwVkKzDcRmKCd2YwE1iNLeGWJz7tz1c+hGeadej0aHgUxBw+hHu6DhS9AyvtwmNweQpc3PnQ==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "node_modules/@ckeditor/ckeditor5-theme-lark": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-theme-lark/-/ckeditor5-theme-lark-42.0.2.tgz",
-            "integrity": "sha512-t+/JVtK+lWzfLywsZX7eE8tfyBSnsaTsxeo84ZbSU9M1Vts5FN/5JExiY89VjsT8m84VAufbG+fDGjQpiYzsyg==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-41.3.1.tgz",
+            "integrity": "sha512-a/LAPO+O9fwHjQ/8s3UNtyrqQRieAnpnPw2IhLlGqOS7nxPKMR2vkb6WnG2LUdO+wYqkCzxUDpBlfVkjkQEI0w==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-ui": "42.0.2"
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-ui": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1"
             }
         },
         "node_modules/@ckeditor/ckeditor5-typing": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-42.0.2.tgz",
-            "integrity": "sha512-xwGazKjCJOQViGnk/Q0yVg98mc0aDJHvx6FsCFRF6e7B8WiMq8rPQjfO63TYOnUSOIkQJerbAv+hrsBS8XdxaQ==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-41.3.1.tgz",
+            "integrity": "sha512-4Oeafc3if6fTITOest1ILQ573fnkzE9/tn5eNm3zWnHVYR79mRCYxaha9yUlKVQiqaxZ48EVo2FjHiouXmn9+Q==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-engine": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1",
                 "lodash-es": "4.17.21"
             }
         },
         "node_modules/@ckeditor/ckeditor5-ui": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-42.0.2.tgz",
-            "integrity": "sha512-Lrej61+xTTqIJSlA9FfqwpEClVoRabM3na8MDiWjAzneQkPgFtw1WTgUKvxNaI+eMXCmT/HVNj/RCg9vqt0pug==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-41.3.1.tgz",
+            "integrity": "sha512-xN7OAiRp7ALKYXUp6Qe/AjkjrhyLuoz9nxq7Jdsnsyb/XXfsXDloMcOuvNRoUgr4gIFHMOoZZxsIn8qegBvcYA==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1",
                 "color-convert": "2.0.1",
                 "color-parse": "1.4.2",
                 "lodash-es": "4.17.21",
@@ -682,147 +113,78 @@
             }
         },
         "node_modules/@ckeditor/ckeditor5-undo": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-42.0.2.tgz",
-            "integrity": "sha512-OpfdYnADY2MM8nWN5M13BEDDnwL15YHUYUpgMnydgJObZzSnePqgWQSFaBAY5j24eze0a8gyGgnOE5jV6VBm1Q==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-41.3.1.tgz",
+            "integrity": "sha512-PElWTnlIwuQ94mvdhuH7Mno99oocSnOWPMHi9UuWe6+zVgznQwn0f0diBZvX3l5y8hFgK6q/pQ/CCmbvvYnovA==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2"
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-engine": "41.3.1",
+                "@ckeditor/ckeditor5-ui": "41.3.1"
             }
         },
         "node_modules/@ckeditor/ckeditor5-upload": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-42.0.2.tgz",
-            "integrity": "sha512-QD6PR1ZurGQv0gULG4hNiaFMO306qM9Gin2BbICkZuJ+IFKd7nQ+mp7ZCbgPgRYtSkeUyHjSzNR4+wIA2nPVEg==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-41.3.1.tgz",
+            "integrity": "sha512-ugTgGEgA9qsSl5+qptTmawdfYaONr6b3uTG4byZ76JMdf0qiniZjBF/TtGAVmBkCipcVWFoaZKteiz0fhQMHjA==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2"
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1"
             }
         },
         "node_modules/@ckeditor/ckeditor5-utils": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-42.0.2.tgz",
-            "integrity": "sha512-z4lNVoVf4cyK6cugMABNgMtYDiIK+0eQwYFtr45DhPK283RWEqrU0xwbwoqhIqeXRQ6B+9+0nC7ZIFPEdQ+iDA==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-41.3.1.tgz",
+            "integrity": "sha512-jJu9ndn6Y7+ffBYdDCRXX7OnV9Ddgms2HSF1pmhjZN0uoL96XworuUOn8hx3Zs/KBPjJEwbtYWJMjG9aohrgaQ==",
             "dev": true,
             "dependencies": {
                 "lodash-es": "4.17.21"
             }
         },
         "node_modules/@ckeditor/ckeditor5-watchdog": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-42.0.2.tgz",
-            "integrity": "sha512-0z00yqbBt/JALAD8C62LNySitQ+wBw1My43Qe2xs5VAP5tUZcziFFCc4BhMy+w6ZWUmZj2hkjSLlmx7b/vid+A==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-41.3.1.tgz",
+            "integrity": "sha512-iDwdYxC8euSKxfRq4y5vVOX9GVUbEbC9z6glkXpxa1BogqYh39+fywjt+s4o3Ub3b8FJ/EUYuNc+/vK+CzEg4g==",
             "dev": true,
             "dependencies": {
                 "lodash-es": "4.17.21"
             }
         },
         "node_modules/@ckeditor/ckeditor5-widget": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-42.0.2.tgz",
-            "integrity": "sha512-ZRI8H+Ir7YpByUO4/kKMNJJE5WUDoICl1BitSR9QKmkG7X2fBRdDG8setm4HsUU1kkPe0aYy6HK2ajZ2g5ZkaA==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-41.3.1.tgz",
+            "integrity": "sha512-rdBxGS3bxWNhp+yxyBYkcbRV6/mdTDab+konDVhZ/ME1jVZ5cf8OBZcgHUqAxzuWt4XMEdzKINbo1OnSDwApUg==",
             "dev": true,
             "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-enter": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-engine": "41.3.1",
+                "@ckeditor/ckeditor5-enter": "41.3.1",
+                "@ckeditor/ckeditor5-typing": "41.3.1",
+                "@ckeditor/ckeditor5-ui": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1",
                 "lodash-es": "4.17.21"
             }
         },
-        "node_modules/@ckeditor/ckeditor5-word-count": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-word-count/-/ckeditor5-word-count-42.0.2.tgz",
-            "integrity": "sha512-jtlyA6TXnnRpaTgvYG219z5p+MRZWUBz3r5oHa79lFcMDREZH6gKztiE+hYSmiL2OSAtHi0kYWUAF/oJfpHt3g==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "node_modules/@mixmark-io/domino": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz",
-            "integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==",
-            "dev": true
-        },
-        "node_modules/blurhash": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/blurhash/-/blurhash-2.0.5.tgz",
-            "integrity": "sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==",
-            "dev": true
-        },
         "node_modules/ckeditor5": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-42.0.2.tgz",
-            "integrity": "sha512-SHyyJ6y/+2Mas3SMlVchsq1i9LYqF7J7EMwEUKAt+sIXBW9pbBnLVncXpIpGTQ/M8fS20NVk7dfJ2P4TyEZGew==",
-            "dev": true,
-            "dependencies": {
-                "@ckeditor/ckeditor5-adapter-ckfinder": "42.0.2",
-                "@ckeditor/ckeditor5-alignment": "42.0.2",
-                "@ckeditor/ckeditor5-autoformat": "42.0.2",
-                "@ckeditor/ckeditor5-autosave": "42.0.2",
-                "@ckeditor/ckeditor5-basic-styles": "42.0.2",
-                "@ckeditor/ckeditor5-block-quote": "42.0.2",
-                "@ckeditor/ckeditor5-ckbox": "42.0.2",
-                "@ckeditor/ckeditor5-ckfinder": "42.0.2",
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-cloud-services": "42.0.2",
-                "@ckeditor/ckeditor5-code-block": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-easy-image": "42.0.2",
-                "@ckeditor/ckeditor5-editor-balloon": "42.0.2",
-                "@ckeditor/ckeditor5-editor-classic": "42.0.2",
-                "@ckeditor/ckeditor5-editor-decoupled": "42.0.2",
-                "@ckeditor/ckeditor5-editor-inline": "42.0.2",
-                "@ckeditor/ckeditor5-editor-multi-root": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-enter": "42.0.2",
-                "@ckeditor/ckeditor5-essentials": "42.0.2",
-                "@ckeditor/ckeditor5-find-and-replace": "42.0.2",
-                "@ckeditor/ckeditor5-font": "42.0.2",
-                "@ckeditor/ckeditor5-heading": "42.0.2",
-                "@ckeditor/ckeditor5-highlight": "42.0.2",
-                "@ckeditor/ckeditor5-horizontal-line": "42.0.2",
-                "@ckeditor/ckeditor5-html-embed": "42.0.2",
-                "@ckeditor/ckeditor5-html-support": "42.0.2",
-                "@ckeditor/ckeditor5-image": "42.0.2",
-                "@ckeditor/ckeditor5-indent": "42.0.2",
-                "@ckeditor/ckeditor5-language": "42.0.2",
-                "@ckeditor/ckeditor5-link": "42.0.2",
-                "@ckeditor/ckeditor5-list": "42.0.2",
-                "@ckeditor/ckeditor5-markdown-gfm": "42.0.2",
-                "@ckeditor/ckeditor5-media-embed": "42.0.2",
-                "@ckeditor/ckeditor5-mention": "42.0.2",
-                "@ckeditor/ckeditor5-minimap": "42.0.2",
-                "@ckeditor/ckeditor5-page-break": "42.0.2",
-                "@ckeditor/ckeditor5-paragraph": "42.0.2",
-                "@ckeditor/ckeditor5-paste-from-office": "42.0.2",
-                "@ckeditor/ckeditor5-remove-format": "42.0.2",
-                "@ckeditor/ckeditor5-restricted-editing": "42.0.2",
-                "@ckeditor/ckeditor5-select-all": "42.0.2",
-                "@ckeditor/ckeditor5-show-blocks": "42.0.2",
-                "@ckeditor/ckeditor5-source-editing": "42.0.2",
-                "@ckeditor/ckeditor5-special-characters": "42.0.2",
-                "@ckeditor/ckeditor5-style": "42.0.2",
-                "@ckeditor/ckeditor5-table": "42.0.2",
-                "@ckeditor/ckeditor5-theme-lark": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-undo": "42.0.2",
-                "@ckeditor/ckeditor5-upload": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-watchdog": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "@ckeditor/ckeditor5-word-count": "42.0.2"
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-41.3.1.tgz",
+            "integrity": "sha512-pBK1YZV9Sy4R53XG70TEeLFOvTFC7tg8AmS6d6zizegtwkH8seblkcERkykcNuvmfzZ/2h9JbafJ4kisZOwiUQ==",
+            "dev": true,
+            "dependencies": {
+                "@ckeditor/ckeditor5-clipboard": "41.3.1",
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-engine": "41.3.1",
+                "@ckeditor/ckeditor5-enter": "41.3.1",
+                "@ckeditor/ckeditor5-paragraph": "41.3.1",
+                "@ckeditor/ckeditor5-select-all": "41.3.1",
+                "@ckeditor/ckeditor5-typing": "41.3.1",
+                "@ckeditor/ckeditor5-ui": "41.3.1",
+                "@ckeditor/ckeditor5-undo": "41.3.1",
+                "@ckeditor/ckeditor5-upload": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1",
+                "@ckeditor/ckeditor5-watchdog": "41.3.1",
+                "@ckeditor/ckeditor5-widget": "41.3.1"
             }
         },
         "node_modules/color-convert": {
@@ -858,33 +220,6 @@
             "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
             "dev": true
         },
-        "node_modules/marked": {
-            "version": "4.0.12",
-            "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz",
-            "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==",
-            "dev": true,
-            "bin": {
-                "marked": "bin/marked.js"
-            },
-            "engines": {
-                "node": ">= 12"
-            }
-        },
-        "node_modules/turndown": {
-            "version": "7.2.0",
-            "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.0.tgz",
-            "integrity": "sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==",
-            "dev": true,
-            "dependencies": {
-                "@mixmark-io/domino": "^2.2.0"
-            }
-        },
-        "node_modules/turndown-plugin-gfm": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.2.tgz",
-            "integrity": "sha512-vwz9tfvF7XN/jE0dGoBei3FXWuvll78ohzCZQuOb+ZjWrs3a0XhQVomJEb2Qh4VHTPNRO4GPZh0V7VRbiWwkRg==",
-            "dev": true
-        },
         "node_modules/vanilla-colorful": {
             "version": "0.7.2",
             "resolved": "https://registry.npmjs.org/vanilla-colorful/-/vanilla-colorful-0.7.2.tgz",
@@ -893,673 +228,104 @@
         }
     },
     "dependencies": {
-        "@ckeditor/ckeditor5-adapter-ckfinder": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-adapter-ckfinder/-/ckeditor5-adapter-ckfinder-42.0.2.tgz",
-            "integrity": "sha512-nX624WYyyJh6BGGy7jNOlEyf+Kv95VWHKlqn39HLTLKlONBp3zBhAtN9rd0gqU5EM6FgPQ+RjOtQinuto0B6oQ==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-upload": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-alignment": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-alignment/-/ckeditor5-alignment-42.0.2.tgz",
-            "integrity": "sha512-g6I0f5Ko7tckHrKYyZhNQL3dGHTcMbjypIfEkk3SAv68X4bDKLImVUJ1L6y0aZnGNoI40cMr0byEyln5rOq67Q==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-autoformat": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autoformat/-/ckeditor5-autoformat-42.0.2.tgz",
-            "integrity": "sha512-tnMdNc8VJ4y4wqbkSAbBGRiUukByOo1nBqyvzYS+SZ2Wzo67OmzKybvqz60PFYIbPAQJa0/uFkvgd55c+VTaqg==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-autosave": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autosave/-/ckeditor5-autosave-42.0.2.tgz",
-            "integrity": "sha512-QIsftrJ6LjJrmUTDfJYpBKy9DJ79ltt2pMHtb8DhoyugGZUup40pFvMrt/4/UuQRm64jS/IjhwWXkSMg4PejJw==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "@ckeditor/ckeditor5-basic-styles": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-basic-styles/-/ckeditor5-basic-styles-42.0.2.tgz",
-            "integrity": "sha512-LT0Kk1K30z/YhI48QBDa69tjU1G2ljSKi5pU5pfiSBLhMl1ShLmXIAy6cEHnijHS0mte8FGwhiGXmNB/jAZ7Iw==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-block-quote": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-block-quote/-/ckeditor5-block-quote-42.0.2.tgz",
-            "integrity": "sha512-xfX+tdAhn7WPHNNZR5Wkjl+OnmbNlEOVVZCL2iAjfswf4r3CglLnJOa529FO+4MyNcwkP+joQ3iVBclZNbETLw==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-enter": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-ckbox": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ckbox/-/ckeditor5-ckbox-42.0.2.tgz",
-            "integrity": "sha512-RvCUphlhrTuGBy78kEOFJvdvmP3o7ajibubOOpVfUMz1V8BbTmmx1+XaveCDxznkwiCLUwqZplWZnpPoEABj2w==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-upload": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "blurhash": "2.0.5",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "@ckeditor/ckeditor5-ckfinder": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ckfinder/-/ckeditor5-ckfinder-42.0.2.tgz",
-            "integrity": "sha512-3lkMF+9Z3R1OUfwZJdORlRDgPSyR9Be57zgizpevpKTenxrZ+UU33ib/kvK8LXVDOzz3qp7UyCucLfY1KNXCzA==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
         "@ckeditor/ckeditor5-clipboard": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-42.0.2.tgz",
-            "integrity": "sha512-x76SjAhaguwVQtJSgz62q96RsJsw0eSM7ZnuUqLjMMzO+hq2hAj7ZIJNPcA46ZyDR6LDQzH760IumSz0xlHn9w==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-41.3.1.tgz",
+            "integrity": "sha512-6S7tq6FlnHYZmPACeqdf135Jx2bTKHVY8mHQ+CHC8ZZu0XVm62vVeeSLS2IcdtYmHjf4ced1G7suTUBHlfBCLw==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "@ckeditor/ckeditor5-cloud-services": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-cloud-services/-/ckeditor5-cloud-services-42.0.2.tgz",
-            "integrity": "sha512-oNdtgD/suEh5nAndXsjik8HgRDk095EGxkmrMO+Z3gbOit28fvTDL6bbUOQvenoNNWa7RXLZMbfyiTMuNH+X8Q==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-code-block": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-code-block/-/ckeditor5-code-block-42.0.2.tgz",
-            "integrity": "sha512-NFGn+350VS6/UNhHm9CurOLm3ZiXFUCO/SgKRILPKZ82Wh2GQqocs5O3yvvo1WQ9jA2DEwjfN0TgOpwgVOZQPQ==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-enter": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-engine": "41.3.1",
+                "@ckeditor/ckeditor5-ui": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1",
+                "@ckeditor/ckeditor5-widget": "41.3.1",
                 "lodash-es": "4.17.21"
             }
         },
         "@ckeditor/ckeditor5-core": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-42.0.2.tgz",
-            "integrity": "sha512-LkNx1Qpk/gwh0wYkl4FdZfi1N2G5Gmp026sVp301boyE9sSVeR3YxcSdKXfsr2HII+7EdJHxMswTvnd/L+IdSg==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-41.3.1.tgz",
+            "integrity": "sha512-h+PgPtCpS2vjO3HbKMYtddRPW+B3AJx9qpixmHJnUZMiFCmRjUZjXATjpi3j+kSQISs4L2Yghq+lsAQxyGHb+A==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-watchdog": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "@ckeditor/ckeditor5-easy-image": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-easy-image/-/ckeditor5-easy-image-42.0.2.tgz",
-            "integrity": "sha512-JYVpX6lRVRve8roROx5y6nsixLXLuVwIokBLoo+usS313xeeZvjoLrxGTeRuyyVbK3BFPE+zqyXsgqGs1Q0stg==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-upload": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-editor-balloon": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-balloon/-/ckeditor5-editor-balloon-42.0.2.tgz",
-            "integrity": "sha512-NXTVQ3aBW8OirKgv8PJvjSDDbl39JGlnS/W+/LRwUlOgHVVWHVSMMqY52AhP90TzP6xfbFYBYX8n13EB6o/4Bw==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "@ckeditor/ckeditor5-editor-classic": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-classic/-/ckeditor5-editor-classic-42.0.2.tgz",
-            "integrity": "sha512-K9+154AP/OpxDn6702772QCiT830lAQXsiUty1Z35MM3hVS5quwkuxS6V0NjKxx0AcqUmmgdXoFxx6v4mj3R7g==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "@ckeditor/ckeditor5-editor-decoupled": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-decoupled/-/ckeditor5-editor-decoupled-42.0.2.tgz",
-            "integrity": "sha512-ANhlpcZXV+nZl/f9o+wS5vqc+Va5K4LnYA0F/pJNTNlighVCa1nGQX11tRGm48vItpNlgQxty+p86NHa+7YrLw==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
+                "@ckeditor/ckeditor5-engine": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1",
                 "lodash-es": "4.17.21"
             }
         },
         "@ckeditor/ckeditor5-editor-inline": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-inline/-/ckeditor5-editor-inline-42.0.2.tgz",
-            "integrity": "sha512-gWngpGE/6JDCyKpKTX7iIgFaxrDPzocZt56p1JmBJCNpVQb4sGoZs94uUg7rxlVo8t3PDH+foL49gSdBKYS9uw==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-inline/-/ckeditor5-editor-inline-41.3.1.tgz",
+            "integrity": "sha512-bAhs57qbeGT907yFsUUxdujtrNlmOTJK4DrBCsxoKSoSo8fcG4D05g/I4ehQp3A1CFYsF2Wkx58TtI/fwWRVbQ==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "@ckeditor/ckeditor5-editor-multi-root": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-multi-root/-/ckeditor5-editor-multi-root-42.0.2.tgz",
-            "integrity": "sha512-1Cv4WGB75KoWZWewCOnHP4s4HGFXKt3BajvDkN8LXS6CtaIPDkH18okY/ivH/Idhu1pT9k2bjzCfR7W4EhtRJg==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
+                "ckeditor5": "41.3.1",
                 "lodash-es": "4.17.21"
             }
         },
         "@ckeditor/ckeditor5-engine": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-42.0.2.tgz",
-            "integrity": "sha512-mI4+X6Z0ihnyAKzka5RjoUgZoaRDckMniN8LLYNum3ewz+KWIVjtHn6NBrqEqw24BpwYfSVEPL/NdgA6xl93Jw==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-41.3.1.tgz",
+            "integrity": "sha512-Me4cnkCrknDH50db/jPczuhgzaxUhHbkh2gv8N8Ypken9ZnOPvMD9W1gCFFTLaxikpPmBQwk3u1BSjOKk3r6kw==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-utils": "41.3.1",
                 "lodash-es": "4.17.21"
             }
         },
         "@ckeditor/ckeditor5-enter": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-42.0.2.tgz",
-            "integrity": "sha512-pzVXQPdBgskiqVpCG/yxliuEXPECCI3GJ/OF5wXs2GQ04IcqBz5FsazUtSLS5nnA4e3YpcdzzEC0Kn1ASdl7QQ==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-essentials": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-essentials/-/ckeditor5-essentials-42.0.2.tgz",
-            "integrity": "sha512-4qhW/7zm69KHnotKEs05YB6YTD6WB6QWJ6U44V6dFGJUUUmYN1fOt9ri6lU8snUVhJrU0C9IuGpVkb8Aby79GQ==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-enter": "42.0.2",
-                "@ckeditor/ckeditor5-select-all": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-undo": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-find-and-replace": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-find-and-replace/-/ckeditor5-find-and-replace-42.0.2.tgz",
-            "integrity": "sha512-9Fc5nKUhDtivHxGoY5nEvwjqUyvMwcNs1Xo6nt9aXeG0gd4mrCdUQaQfRIlcycLmeVD1MgKfWh7sOv+EtuYFRA==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "@ckeditor/ckeditor5-font": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-font/-/ckeditor5-font-42.0.2.tgz",
-            "integrity": "sha512-Soj1auf82Zz6y56qKf6nV6RSjNPENZm9vpkJ9jhyQ4pMh6YvQ7EkzbOwPCoskXm+ab8EAuH+bjS0n5lewN5i7Q==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-heading": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-heading/-/ckeditor5-heading-42.0.2.tgz",
-            "integrity": "sha512-1lwxsxzJRikSerwhH1By9FlAO2EQhcrt3xnpxBFME3pS2Y6tbkHj81W5Lu2cf+0ew5Bzcp5uqTvaArRtVssY1A==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-paragraph": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-highlight": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-highlight/-/ckeditor5-highlight-42.0.2.tgz",
-            "integrity": "sha512-I/qVqC1YS6Hfg1dZjP665NU2fIx5Dk4Rjq2ku7yxQrsmG+rle2xrEzXF1BsaBeK6ko+fX7JaP86dTvywnnOeaw==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-horizontal-line": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-horizontal-line/-/ckeditor5-horizontal-line-42.0.2.tgz",
-            "integrity": "sha512-zXnK2k5F5lhbLVwHzyURPMRGc8pc1YPz8fYXmz1pf/JG/EgXGGuUlczkpzegBUb9MctFgZbs09xIkTkVBQZmNw==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-html-embed": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-html-embed/-/ckeditor5-html-embed-42.0.2.tgz",
-            "integrity": "sha512-aqCV9vQJd6KiYsTEW6UlWtyMTZgXI2oHK7/1p8WUagabHU1ZFT+jkExC8QG9n0M76Sq9TIynqBlfl4OOijT6NQ==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-html-support": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-html-support/-/ckeditor5-html-support-42.0.2.tgz",
-            "integrity": "sha512-z+Tg/jOf9+wzCo/NywkuHPGfOnKHfSr0hvkGjrq8b2OU9B1nJI34VTjJWSFH5NfLpn3tZo2dy3EcaoN9B7rSHA==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-41.3.1.tgz",
+            "integrity": "sha512-iwhvJpfsutqcv/bf8QPMKhMolb7GtShaOT+UIDW3OXjMZaBKZOTyR8OceijwgBmZeillTaXQq9y2e9lbJd46xg==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-enter": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "@ckeditor/ckeditor5-image": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-image/-/ckeditor5-image-42.0.2.tgz",
-            "integrity": "sha512-RH1r10rsnEFSBNBXe3d02J6JDvoLKxwz/KCvC/EoOR4UEKDe0FNodt3+VZrb0JNqkBUIxqdtvEobXb6YmGQaDQ==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-undo": "42.0.2",
-                "@ckeditor/ckeditor5-upload": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "@ckeditor/ckeditor5-indent": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-indent/-/ckeditor5-indent-42.0.2.tgz",
-            "integrity": "sha512-qXVXqvflW8kKa7odjiSTrQtj75C5opmnGUyrM+37f7CC8OmrcjXJ5GgrFnKwHyny9YHtvQyyN+GCuzuir6a9eA==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-language": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-language/-/ckeditor5-language-42.0.2.tgz",
-            "integrity": "sha512-s0pMdNxuE+kBCFiop5Lgv/UsYAYLKCENesMXVIRrxI73GRjwJXIq5f/5a7xwvfmH3/TQT5GMrfNmf5EeYo5NHA==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-link": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-link/-/ckeditor5-link-42.0.2.tgz",
-            "integrity": "sha512-KySX11v1RyimZyc4u3AF6a/bEvA3gQg/krRsrzBbMIadtC1WN/C7w7XzjmYvx8Ui0SsH/ChBu16SxmRKO4HuTA==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "@ckeditor/ckeditor5-list": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-list/-/ckeditor5-list-42.0.2.tgz",
-            "integrity": "sha512-NTNDb01QDyjDZis8nyOsvgSNwy6YniulGDZdyeulhmFy6zyHG0GFeYA0kAyW6/bnniWyW9cpfUrAK9KTLuql4A==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-enter": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-markdown-gfm": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-markdown-gfm/-/ckeditor5-markdown-gfm-42.0.2.tgz",
-            "integrity": "sha512-mh81YHQqVF0ZVSgd7hbO3EzuM78zIhwwZiiVsJ68e4aCfpYjc3Ni1NpyORj+tian743PmFr7WAUqIePdNPmQEg==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "marked": "4.0.12",
-                "turndown": "7.2.0",
-                "turndown-plugin-gfm": "1.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-media-embed": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-media-embed/-/ckeditor5-media-embed-42.0.2.tgz",
-            "integrity": "sha512-iXGcfgOm0IWa600ln5YeSssg7Sew6Lf1z9ziTxsQsmforPIqXgZQEvdLoo0tABddSRQZI+yQZnRnwrus9sZXIA==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-undo": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-mention": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-mention/-/ckeditor5-mention-42.0.2.tgz",
-            "integrity": "sha512-81MYULfB7bHDb5Y7saIZMkNVG1BJV/ir5BwIDuuXwGXLNVX++uMTK4ryAItYToiSFN8/NBms7JFXPrRhL/zbOw==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "@ckeditor/ckeditor5-minimap": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-minimap/-/ckeditor5-minimap-42.0.2.tgz",
-            "integrity": "sha512-dOBT6bS/7tREFmpRCD4XwOEmoW4p7ZV1Pp3tA/KYQ++2BAgI/O/Yeww7nlhsKhal4r74v459hgihI/SnlfqBQA==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-page-break": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-page-break/-/ckeditor5-page-break-42.0.2.tgz",
-            "integrity": "sha512-h6Wb0fWsl4a0MyU8W3F4Yku/1CWnR6tQrcMapn0sHB9W/HAvHLQIJGdsYh+a1W6QzMIjpVAqjT4mxQ1rU86RkQ==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "ckeditor5": "42.0.2"
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-engine": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1"
             }
         },
         "@ckeditor/ckeditor5-paragraph": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-42.0.2.tgz",
-            "integrity": "sha512-feI7Rw76uPbPmoFeVEPpKdPTOjdlccpWabhfrimgT08rECLa7ErFw2oRZVmnx5+kjX+NAUeD9kaUZUUkNNP0wg==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-paste-from-office": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paste-from-office/-/ckeditor5-paste-from-office-42.0.2.tgz",
-            "integrity": "sha512-9K54E44rEjvLqWKRRHeifOlb1bICKzzX8gOv/i90sFQfMeQphA6qEn3WJZNQY4NY9Uwhu3kF/gh3/dqlcBhsvw==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-41.3.1.tgz",
+            "integrity": "sha512-weRPLyO/1Z8PpU9+lET4gYgJ8adDuCjYiREup81URSuS1DDQ8vb3D29xA+4Ov7lwg8BaNAMCpTBdp07GHHzv6w==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-remove-format": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-remove-format/-/ckeditor5-remove-format-42.0.2.tgz",
-            "integrity": "sha512-YIyKibU44Jt6P9qu3WGPjUUh/pb5dvexeE1XG6f5JNtVlZCy3sUI+BDytzqWI68/coOHBKYkKSDOEQdzw83PdA==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-restricted-editing": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-restricted-editing/-/ckeditor5-restricted-editing-42.0.2.tgz",
-            "integrity": "sha512-tfnEE6ieR2UhjZ9zoDNfXIMAMy2FWoajASKffdtpTMBjkVKzM+isg8j0hEkWgiQqCsJYVWt0314nPZrm5EUIfA==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-ui": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1"
             }
         },
         "@ckeditor/ckeditor5-select-all": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-42.0.2.tgz",
-            "integrity": "sha512-eqLhxmsxDQ8s+Op4f0OoXbN9vwz0hekE1HxsClXIsqwhjsO2o/HYcyhIzR9lPgmi4bVf8uy8T9oyWQNRLv4S9w==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-show-blocks": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-show-blocks/-/ckeditor5-show-blocks-42.0.2.tgz",
-            "integrity": "sha512-CFYJN3gyiWwJ1mDonzIktRL/A+WONZuyCptELqlU51RRCwbG7eSMtu2Eyd+Q463zYbOKZcdr5uNvlWuRpSsalw==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-source-editing": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-source-editing/-/ckeditor5-source-editing-42.0.2.tgz",
-            "integrity": "sha512-lo/ZmBeAoWu9j0qfuUVIpc2QzZmcrYZ2enloz2mL22DCn3eP8IstE7gSmZlQ/DQxcPC5Sf2uC0l9IurBAP9+pg==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-theme-lark": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-special-characters": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-special-characters/-/ckeditor5-special-characters-42.0.2.tgz",
-            "integrity": "sha512-B2E9thXW0Ej1istiResH6987g+REnX18aoxW4uXG+PHDrYWjsV4fClEnjWdkO/O0A3yOoNc4LYAbGSo7z0g/1g==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2"
-            }
-        },
-        "@ckeditor/ckeditor5-style": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-style/-/ckeditor5-style-42.0.2.tgz",
-            "integrity": "sha512-vq1GSeOtZm00W4FC6MgqukJbdDE394Sh7ID6634gKmdknbxOBvNcF0XUdAu+kWtJzTjYVrC4+oPYpS5C+odidQ==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "@ckeditor/ckeditor5-table": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-table/-/ckeditor5-table-42.0.2.tgz",
-            "integrity": "sha512-fFMXbQCa7UR4aAmwVkKzDcRmKCd2YwE1iNLeGWJz7tz1c+hGeadej0aHgUxBw+hHu6DhS9AyvtwmNweQpc3PnQ==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-41.3.1.tgz",
+            "integrity": "sha512-a/LAPO+O9fwHjQ/8s3UNtyrqQRieAnpnPw2IhLlGqOS7nxPKMR2vkb6WnG2LUdO+wYqkCzxUDpBlfVkjkQEI0w==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "@ckeditor/ckeditor5-theme-lark": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-theme-lark/-/ckeditor5-theme-lark-42.0.2.tgz",
-            "integrity": "sha512-t+/JVtK+lWzfLywsZX7eE8tfyBSnsaTsxeo84ZbSU9M1Vts5FN/5JExiY89VjsT8m84VAufbG+fDGjQpiYzsyg==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-ui": "42.0.2"
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-ui": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1"
             }
         },
         "@ckeditor/ckeditor5-typing": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-42.0.2.tgz",
-            "integrity": "sha512-xwGazKjCJOQViGnk/Q0yVg98mc0aDJHvx6FsCFRF6e7B8WiMq8rPQjfO63TYOnUSOIkQJerbAv+hrsBS8XdxaQ==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-41.3.1.tgz",
+            "integrity": "sha512-4Oeafc3if6fTITOest1ILQ573fnkzE9/tn5eNm3zWnHVYR79mRCYxaha9yUlKVQiqaxZ48EVo2FjHiouXmn9+Q==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-engine": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1",
                 "lodash-es": "4.17.21"
             }
         },
         "@ckeditor/ckeditor5-ui": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-42.0.2.tgz",
-            "integrity": "sha512-Lrej61+xTTqIJSlA9FfqwpEClVoRabM3na8MDiWjAzneQkPgFtw1WTgUKvxNaI+eMXCmT/HVNj/RCg9vqt0pug==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-41.3.1.tgz",
+            "integrity": "sha512-xN7OAiRp7ALKYXUp6Qe/AjkjrhyLuoz9nxq7Jdsnsyb/XXfsXDloMcOuvNRoUgr4gIFHMOoZZxsIn8qegBvcYA==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1",
                 "color-convert": "2.0.1",
                 "color-parse": "1.4.2",
                 "lodash-es": "4.17.21",
@@ -1567,147 +333,78 @@
             }
         },
         "@ckeditor/ckeditor5-undo": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-42.0.2.tgz",
-            "integrity": "sha512-OpfdYnADY2MM8nWN5M13BEDDnwL15YHUYUpgMnydgJObZzSnePqgWQSFaBAY5j24eze0a8gyGgnOE5jV6VBm1Q==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-41.3.1.tgz",
+            "integrity": "sha512-PElWTnlIwuQ94mvdhuH7Mno99oocSnOWPMHi9UuWe6+zVgznQwn0f0diBZvX3l5y8hFgK6q/pQ/CCmbvvYnovA==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2"
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-engine": "41.3.1",
+                "@ckeditor/ckeditor5-ui": "41.3.1"
             }
         },
         "@ckeditor/ckeditor5-upload": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-42.0.2.tgz",
-            "integrity": "sha512-QD6PR1ZurGQv0gULG4hNiaFMO306qM9Gin2BbICkZuJ+IFKd7nQ+mp7ZCbgPgRYtSkeUyHjSzNR4+wIA2nPVEg==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-41.3.1.tgz",
+            "integrity": "sha512-ugTgGEgA9qsSl5+qptTmawdfYaONr6b3uTG4byZ76JMdf0qiniZjBF/TtGAVmBkCipcVWFoaZKteiz0fhQMHjA==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2"
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1"
             }
         },
         "@ckeditor/ckeditor5-utils": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-42.0.2.tgz",
-            "integrity": "sha512-z4lNVoVf4cyK6cugMABNgMtYDiIK+0eQwYFtr45DhPK283RWEqrU0xwbwoqhIqeXRQ6B+9+0nC7ZIFPEdQ+iDA==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-41.3.1.tgz",
+            "integrity": "sha512-jJu9ndn6Y7+ffBYdDCRXX7OnV9Ddgms2HSF1pmhjZN0uoL96XworuUOn8hx3Zs/KBPjJEwbtYWJMjG9aohrgaQ==",
             "dev": true,
             "requires": {
                 "lodash-es": "4.17.21"
             }
         },
         "@ckeditor/ckeditor5-watchdog": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-42.0.2.tgz",
-            "integrity": "sha512-0z00yqbBt/JALAD8C62LNySitQ+wBw1My43Qe2xs5VAP5tUZcziFFCc4BhMy+w6ZWUmZj2hkjSLlmx7b/vid+A==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-41.3.1.tgz",
+            "integrity": "sha512-iDwdYxC8euSKxfRq4y5vVOX9GVUbEbC9z6glkXpxa1BogqYh39+fywjt+s4o3Ub3b8FJ/EUYuNc+/vK+CzEg4g==",
             "dev": true,
             "requires": {
                 "lodash-es": "4.17.21"
             }
         },
         "@ckeditor/ckeditor5-widget": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-42.0.2.tgz",
-            "integrity": "sha512-ZRI8H+Ir7YpByUO4/kKMNJJE5WUDoICl1BitSR9QKmkG7X2fBRdDG8setm4HsUU1kkPe0aYy6HK2ajZ2g5ZkaA==",
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-41.3.1.tgz",
+            "integrity": "sha512-rdBxGS3bxWNhp+yxyBYkcbRV6/mdTDab+konDVhZ/ME1jVZ5cf8OBZcgHUqAxzuWt4XMEdzKINbo1OnSDwApUg==",
             "dev": true,
             "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-enter": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-engine": "41.3.1",
+                "@ckeditor/ckeditor5-enter": "41.3.1",
+                "@ckeditor/ckeditor5-typing": "41.3.1",
+                "@ckeditor/ckeditor5-ui": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1",
                 "lodash-es": "4.17.21"
             }
         },
-        "@ckeditor/ckeditor5-word-count": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-word-count/-/ckeditor5-word-count-42.0.2.tgz",
-            "integrity": "sha512-jtlyA6TXnnRpaTgvYG219z5p+MRZWUBz3r5oHa79lFcMDREZH6gKztiE+hYSmiL2OSAtHi0kYWUAF/oJfpHt3g==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "ckeditor5": "42.0.2",
-                "lodash-es": "4.17.21"
-            }
-        },
-        "@mixmark-io/domino": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz",
-            "integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==",
-            "dev": true
-        },
-        "blurhash": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/blurhash/-/blurhash-2.0.5.tgz",
-            "integrity": "sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==",
-            "dev": true
-        },
         "ckeditor5": {
-            "version": "42.0.2",
-            "resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-42.0.2.tgz",
-            "integrity": "sha512-SHyyJ6y/+2Mas3SMlVchsq1i9LYqF7J7EMwEUKAt+sIXBW9pbBnLVncXpIpGTQ/M8fS20NVk7dfJ2P4TyEZGew==",
-            "dev": true,
-            "requires": {
-                "@ckeditor/ckeditor5-adapter-ckfinder": "42.0.2",
-                "@ckeditor/ckeditor5-alignment": "42.0.2",
-                "@ckeditor/ckeditor5-autoformat": "42.0.2",
-                "@ckeditor/ckeditor5-autosave": "42.0.2",
-                "@ckeditor/ckeditor5-basic-styles": "42.0.2",
-                "@ckeditor/ckeditor5-block-quote": "42.0.2",
-                "@ckeditor/ckeditor5-ckbox": "42.0.2",
-                "@ckeditor/ckeditor5-ckfinder": "42.0.2",
-                "@ckeditor/ckeditor5-clipboard": "42.0.2",
-                "@ckeditor/ckeditor5-cloud-services": "42.0.2",
-                "@ckeditor/ckeditor5-code-block": "42.0.2",
-                "@ckeditor/ckeditor5-core": "42.0.2",
-                "@ckeditor/ckeditor5-easy-image": "42.0.2",
-                "@ckeditor/ckeditor5-editor-balloon": "42.0.2",
-                "@ckeditor/ckeditor5-editor-classic": "42.0.2",
-                "@ckeditor/ckeditor5-editor-decoupled": "42.0.2",
-                "@ckeditor/ckeditor5-editor-inline": "42.0.2",
-                "@ckeditor/ckeditor5-editor-multi-root": "42.0.2",
-                "@ckeditor/ckeditor5-engine": "42.0.2",
-                "@ckeditor/ckeditor5-enter": "42.0.2",
-                "@ckeditor/ckeditor5-essentials": "42.0.2",
-                "@ckeditor/ckeditor5-find-and-replace": "42.0.2",
-                "@ckeditor/ckeditor5-font": "42.0.2",
-                "@ckeditor/ckeditor5-heading": "42.0.2",
-                "@ckeditor/ckeditor5-highlight": "42.0.2",
-                "@ckeditor/ckeditor5-horizontal-line": "42.0.2",
-                "@ckeditor/ckeditor5-html-embed": "42.0.2",
-                "@ckeditor/ckeditor5-html-support": "42.0.2",
-                "@ckeditor/ckeditor5-image": "42.0.2",
-                "@ckeditor/ckeditor5-indent": "42.0.2",
-                "@ckeditor/ckeditor5-language": "42.0.2",
-                "@ckeditor/ckeditor5-link": "42.0.2",
-                "@ckeditor/ckeditor5-list": "42.0.2",
-                "@ckeditor/ckeditor5-markdown-gfm": "42.0.2",
-                "@ckeditor/ckeditor5-media-embed": "42.0.2",
-                "@ckeditor/ckeditor5-mention": "42.0.2",
-                "@ckeditor/ckeditor5-minimap": "42.0.2",
-                "@ckeditor/ckeditor5-page-break": "42.0.2",
-                "@ckeditor/ckeditor5-paragraph": "42.0.2",
-                "@ckeditor/ckeditor5-paste-from-office": "42.0.2",
-                "@ckeditor/ckeditor5-remove-format": "42.0.2",
-                "@ckeditor/ckeditor5-restricted-editing": "42.0.2",
-                "@ckeditor/ckeditor5-select-all": "42.0.2",
-                "@ckeditor/ckeditor5-show-blocks": "42.0.2",
-                "@ckeditor/ckeditor5-source-editing": "42.0.2",
-                "@ckeditor/ckeditor5-special-characters": "42.0.2",
-                "@ckeditor/ckeditor5-style": "42.0.2",
-                "@ckeditor/ckeditor5-table": "42.0.2",
-                "@ckeditor/ckeditor5-theme-lark": "42.0.2",
-                "@ckeditor/ckeditor5-typing": "42.0.2",
-                "@ckeditor/ckeditor5-ui": "42.0.2",
-                "@ckeditor/ckeditor5-undo": "42.0.2",
-                "@ckeditor/ckeditor5-upload": "42.0.2",
-                "@ckeditor/ckeditor5-utils": "42.0.2",
-                "@ckeditor/ckeditor5-watchdog": "42.0.2",
-                "@ckeditor/ckeditor5-widget": "42.0.2",
-                "@ckeditor/ckeditor5-word-count": "42.0.2"
+            "version": "41.3.1",
+            "resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-41.3.1.tgz",
+            "integrity": "sha512-pBK1YZV9Sy4R53XG70TEeLFOvTFC7tg8AmS6d6zizegtwkH8seblkcERkykcNuvmfzZ/2h9JbafJ4kisZOwiUQ==",
+            "dev": true,
+            "requires": {
+                "@ckeditor/ckeditor5-clipboard": "41.3.1",
+                "@ckeditor/ckeditor5-core": "41.3.1",
+                "@ckeditor/ckeditor5-engine": "41.3.1",
+                "@ckeditor/ckeditor5-enter": "41.3.1",
+                "@ckeditor/ckeditor5-paragraph": "41.3.1",
+                "@ckeditor/ckeditor5-select-all": "41.3.1",
+                "@ckeditor/ckeditor5-typing": "41.3.1",
+                "@ckeditor/ckeditor5-ui": "41.3.1",
+                "@ckeditor/ckeditor5-undo": "41.3.1",
+                "@ckeditor/ckeditor5-upload": "41.3.1",
+                "@ckeditor/ckeditor5-utils": "41.3.1",
+                "@ckeditor/ckeditor5-watchdog": "41.3.1",
+                "@ckeditor/ckeditor5-widget": "41.3.1"
             }
         },
         "color-convert": {
@@ -1740,27 +437,6 @@
             "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
             "dev": true
         },
-        "marked": {
-            "version": "4.0.12",
-            "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz",
-            "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==",
-            "dev": true
-        },
-        "turndown": {
-            "version": "7.2.0",
-            "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.0.tgz",
-            "integrity": "sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==",
-            "dev": true,
-            "requires": {
-                "@mixmark-io/domino": "^2.2.0"
-            }
-        },
-        "turndown-plugin-gfm": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.2.tgz",
-            "integrity": "sha512-vwz9tfvF7XN/jE0dGoBei3FXWuvll78ohzCZQuOb+ZjWrs3a0XhQVomJEb2Qh4VHTPNRO4GPZh0V7VRbiWwkRg==",
-            "dev": true
-        },
         "vanilla-colorful": {
             "version": "0.7.2",
             "resolved": "https://registry.npmjs.org/vanilla-colorful/-/vanilla-colorful-0.7.2.tgz",
diff --git a/package.json b/package.json
index bd524c1..621ee2f 100644
--- a/package.json
+++ b/package.json
@@ -3,6 +3,6 @@
         "vendor-update": "drush edit_plus:update-ckeditor-version; npm install; drush edit_plus:move-library"
     },
     "devDependencies": {
-        "@ckeditor\/ckeditor5-editor-inline": "~42.0.2"
+        "@ckeditor\/ckeditor5-editor-inline": "~41.3.1"
     }
 }
\ No newline at end of file
diff --git a/src/Form/InlineEntityFormAlter.php b/src/Form/InlineEntityFormAlter.php
index 72fdc19..19d34b5 100644
--- a/src/Form/InlineEntityFormAlter.php
+++ b/src/Form/InlineEntityFormAlter.php
@@ -62,7 +62,6 @@ class InlineEntityFormAlter implements EntityFormInterface {
 
     $form['actions']['submit']['#submit'][] = [$this, 'update'];
     $form['actions']['submit']['#value'] = $this->t('Update');
-    $form['actions']['submit']['#ajax']['progress'] = ['type' => 'fullscreen'];
     $form['actions']['submit']['#attributes']['class'][] = 'edit-plus-update-button';
 
     $this->prepareFormForInlineEditing($form, $form_state);
diff --git a/yarn.lock b/yarn.lock
index e6f1464..389dbf2 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,747 +2,180 @@
 # yarn lockfile v1
 
 
-"@ckeditor/ckeditor5-adapter-ckfinder@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-adapter-ckfinder/-/ckeditor5-adapter-ckfinder-42.0.2.tgz"
-  integrity sha512-nX624WYyyJh6BGGy7jNOlEyf+Kv95VWHKlqn39HLTLKlONBp3zBhAtN9rd0gqU5EM6FgPQ+RjOtQinuto0B6oQ==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-upload" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-alignment@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-alignment/-/ckeditor5-alignment-42.0.2.tgz"
-  integrity sha512-g6I0f5Ko7tckHrKYyZhNQL3dGHTcMbjypIfEkk3SAv68X4bDKLImVUJ1L6y0aZnGNoI40cMr0byEyln5rOq67Q==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-autoformat@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-autoformat/-/ckeditor5-autoformat-42.0.2.tgz"
-  integrity sha512-tnMdNc8VJ4y4wqbkSAbBGRiUukByOo1nBqyvzYS+SZ2Wzo67OmzKybvqz60PFYIbPAQJa0/uFkvgd55c+VTaqg==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-typing" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-autosave@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-autosave/-/ckeditor5-autosave-42.0.2.tgz"
-  integrity sha512-QIsftrJ6LjJrmUTDfJYpBKy9DJ79ltt2pMHtb8DhoyugGZUup40pFvMrt/4/UuQRm64jS/IjhwWXkSMg4PejJw==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-basic-styles@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-basic-styles/-/ckeditor5-basic-styles-42.0.2.tgz"
-  integrity sha512-LT0Kk1K30z/YhI48QBDa69tjU1G2ljSKi5pU5pfiSBLhMl1ShLmXIAy6cEHnijHS0mte8FGwhiGXmNB/jAZ7Iw==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-typing" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-block-quote@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-block-quote/-/ckeditor5-block-quote-42.0.2.tgz"
-  integrity sha512-xfX+tdAhn7WPHNNZR5Wkjl+OnmbNlEOVVZCL2iAjfswf4r3CglLnJOa529FO+4MyNcwkP+joQ3iVBclZNbETLw==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-enter" "42.0.2"
-    "@ckeditor/ckeditor5-typing" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-ckbox@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-ckbox/-/ckeditor5-ckbox-42.0.2.tgz"
-  integrity sha512-RvCUphlhrTuGBy78kEOFJvdvmP3o7ajibubOOpVfUMz1V8BbTmmx1+XaveCDxznkwiCLUwqZplWZnpPoEABj2w==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-upload" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    blurhash "2.0.5"
-    ckeditor5 "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-ckfinder@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-ckfinder/-/ckeditor5-ckfinder-42.0.2.tgz"
-  integrity sha512-3lkMF+9Z3R1OUfwZJdORlRDgPSyR9Be57zgizpevpKTenxrZ+UU33ib/kvK8LXVDOzz3qp7UyCucLfY1KNXCzA==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-clipboard@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-42.0.2.tgz"
-  integrity sha512-x76SjAhaguwVQtJSgz62q96RsJsw0eSM7ZnuUqLjMMzO+hq2hAj7ZIJNPcA46ZyDR6LDQzH760IumSz0xlHn9w==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    "@ckeditor/ckeditor5-widget" "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-cloud-services@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-cloud-services/-/ckeditor5-cloud-services-42.0.2.tgz"
-  integrity sha512-oNdtgD/suEh5nAndXsjik8HgRDk095EGxkmrMO+Z3gbOit28fvTDL6bbUOQvenoNNWa7RXLZMbfyiTMuNH+X8Q==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-code-block@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-code-block/-/ckeditor5-code-block-42.0.2.tgz"
-  integrity sha512-NFGn+350VS6/UNhHm9CurOLm3ZiXFUCO/SgKRILPKZ82Wh2GQqocs5O3yvvo1WQ9jA2DEwjfN0TgOpwgVOZQPQ==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-enter" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-core@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-42.0.2.tgz"
-  integrity sha512-LkNx1Qpk/gwh0wYkl4FdZfi1N2G5Gmp026sVp301boyE9sSVeR3YxcSdKXfsr2HII+7EdJHxMswTvnd/L+IdSg==
-  dependencies:
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    "@ckeditor/ckeditor5-watchdog" "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-easy-image@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-easy-image/-/ckeditor5-easy-image-42.0.2.tgz"
-  integrity sha512-JYVpX6lRVRve8roROx5y6nsixLXLuVwIokBLoo+usS313xeeZvjoLrxGTeRuyyVbK3BFPE+zqyXsgqGs1Q0stg==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-upload" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-editor-balloon@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-balloon/-/ckeditor5-editor-balloon-42.0.2.tgz"
-  integrity sha512-NXTVQ3aBW8OirKgv8PJvjSDDbl39JGlnS/W+/LRwUlOgHVVWHVSMMqY52AhP90TzP6xfbFYBYX8n13EB6o/4Bw==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-editor-classic@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-classic/-/ckeditor5-editor-classic-42.0.2.tgz"
-  integrity sha512-K9+154AP/OpxDn6702772QCiT830lAQXsiUty1Z35MM3hVS5quwkuxS6V0NjKxx0AcqUmmgdXoFxx6v4mj3R7g==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-editor-decoupled@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-decoupled/-/ckeditor5-editor-decoupled-42.0.2.tgz"
-  integrity sha512-ANhlpcZXV+nZl/f9o+wS5vqc+Va5K4LnYA0F/pJNTNlighVCa1nGQX11tRGm48vItpNlgQxty+p86NHa+7YrLw==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-editor-inline@~42.0.2", "@ckeditor/ckeditor5-editor-inline@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-inline/-/ckeditor5-editor-inline-42.0.2.tgz"
-  integrity sha512-gWngpGE/6JDCyKpKTX7iIgFaxrDPzocZt56p1JmBJCNpVQb4sGoZs94uUg7rxlVo8t3PDH+foL49gSdBKYS9uw==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-editor-multi-root@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-multi-root/-/ckeditor5-editor-multi-root-42.0.2.tgz"
-  integrity sha512-1Cv4WGB75KoWZWewCOnHP4s4HGFXKt3BajvDkN8LXS6CtaIPDkH18okY/ivH/Idhu1pT9k2bjzCfR7W4EhtRJg==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-engine@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-42.0.2.tgz"
-  integrity sha512-mI4+X6Z0ihnyAKzka5RjoUgZoaRDckMniN8LLYNum3ewz+KWIVjtHn6NBrqEqw24BpwYfSVEPL/NdgA6xl93Jw==
-  dependencies:
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-enter@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-42.0.2.tgz"
-  integrity sha512-pzVXQPdBgskiqVpCG/yxliuEXPECCI3GJ/OF5wXs2GQ04IcqBz5FsazUtSLS5nnA4e3YpcdzzEC0Kn1ASdl7QQ==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-
-"@ckeditor/ckeditor5-essentials@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-essentials/-/ckeditor5-essentials-42.0.2.tgz"
-  integrity sha512-4qhW/7zm69KHnotKEs05YB6YTD6WB6QWJ6U44V6dFGJUUUmYN1fOt9ri6lU8snUVhJrU0C9IuGpVkb8Aby79GQ==
-  dependencies:
-    "@ckeditor/ckeditor5-clipboard" "42.0.2"
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-enter" "42.0.2"
-    "@ckeditor/ckeditor5-select-all" "42.0.2"
-    "@ckeditor/ckeditor5-typing" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-undo" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-find-and-replace@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-find-and-replace/-/ckeditor5-find-and-replace-42.0.2.tgz"
-  integrity sha512-9Fc5nKUhDtivHxGoY5nEvwjqUyvMwcNs1Xo6nt9aXeG0gd4mrCdUQaQfRIlcycLmeVD1MgKfWh7sOv+EtuYFRA==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-font@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-font/-/ckeditor5-font-42.0.2.tgz"
-  integrity sha512-Soj1auf82Zz6y56qKf6nV6RSjNPENZm9vpkJ9jhyQ4pMh6YvQ7EkzbOwPCoskXm+ab8EAuH+bjS0n5lewN5i7Q==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-heading@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-heading/-/ckeditor5-heading-42.0.2.tgz"
-  integrity sha512-1lwxsxzJRikSerwhH1By9FlAO2EQhcrt3xnpxBFME3pS2Y6tbkHj81W5Lu2cf+0ew5Bzcp5uqTvaArRtVssY1A==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-paragraph" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-highlight@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-highlight/-/ckeditor5-highlight-42.0.2.tgz"
-  integrity sha512-I/qVqC1YS6Hfg1dZjP665NU2fIx5Dk4Rjq2ku7yxQrsmG+rle2xrEzXF1BsaBeK6ko+fX7JaP86dTvywnnOeaw==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-horizontal-line@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-horizontal-line/-/ckeditor5-horizontal-line-42.0.2.tgz"
-  integrity sha512-zXnK2k5F5lhbLVwHzyURPMRGc8pc1YPz8fYXmz1pf/JG/EgXGGuUlczkpzegBUb9MctFgZbs09xIkTkVBQZmNw==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-widget" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-html-embed@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-html-embed/-/ckeditor5-html-embed-42.0.2.tgz"
-  integrity sha512-aqCV9vQJd6KiYsTEW6UlWtyMTZgXI2oHK7/1p8WUagabHU1ZFT+jkExC8QG9n0M76Sq9TIynqBlfl4OOijT6NQ==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    "@ckeditor/ckeditor5-widget" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-html-support@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-html-support/-/ckeditor5-html-support-42.0.2.tgz"
-  integrity sha512-z+Tg/jOf9+wzCo/NywkuHPGfOnKHfSr0hvkGjrq8b2OU9B1nJI34VTjJWSFH5NfLpn3tZo2dy3EcaoN9B7rSHA==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-enter" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    "@ckeditor/ckeditor5-widget" "42.0.2"
-    ckeditor5 "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-image@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-image/-/ckeditor5-image-42.0.2.tgz"
-  integrity sha512-RH1r10rsnEFSBNBXe3d02J6JDvoLKxwz/KCvC/EoOR4UEKDe0FNodt3+VZrb0JNqkBUIxqdtvEobXb6YmGQaDQ==
-  dependencies:
-    "@ckeditor/ckeditor5-clipboard" "42.0.2"
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-typing" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-undo" "42.0.2"
-    "@ckeditor/ckeditor5-upload" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    "@ckeditor/ckeditor5-widget" "42.0.2"
-    ckeditor5 "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-indent@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-indent/-/ckeditor5-indent-42.0.2.tgz"
-  integrity sha512-qXVXqvflW8kKa7odjiSTrQtj75C5opmnGUyrM+37f7CC8OmrcjXJ5GgrFnKwHyny9YHtvQyyN+GCuzuir6a9eA==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-language@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-language/-/ckeditor5-language-42.0.2.tgz"
-  integrity sha512-s0pMdNxuE+kBCFiop5Lgv/UsYAYLKCENesMXVIRrxI73GRjwJXIq5f/5a7xwvfmH3/TQT5GMrfNmf5EeYo5NHA==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-link@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-link/-/ckeditor5-link-42.0.2.tgz"
-  integrity sha512-KySX11v1RyimZyc4u3AF6a/bEvA3gQg/krRsrzBbMIadtC1WN/C7w7XzjmYvx8Ui0SsH/ChBu16SxmRKO4HuTA==
-  dependencies:
-    "@ckeditor/ckeditor5-clipboard" "42.0.2"
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-typing" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    "@ckeditor/ckeditor5-widget" "42.0.2"
-    ckeditor5 "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-list@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-list/-/ckeditor5-list-42.0.2.tgz"
-  integrity sha512-NTNDb01QDyjDZis8nyOsvgSNwy6YniulGDZdyeulhmFy6zyHG0GFeYA0kAyW6/bnniWyW9cpfUrAK9KTLuql4A==
-  dependencies:
-    "@ckeditor/ckeditor5-clipboard" "42.0.2"
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-enter" "42.0.2"
-    "@ckeditor/ckeditor5-typing" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-markdown-gfm@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-markdown-gfm/-/ckeditor5-markdown-gfm-42.0.2.tgz"
-  integrity sha512-mh81YHQqVF0ZVSgd7hbO3EzuM78zIhwwZiiVsJ68e4aCfpYjc3Ni1NpyORj+tian743PmFr7WAUqIePdNPmQEg==
-  dependencies:
-    "@ckeditor/ckeditor5-clipboard" "42.0.2"
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    ckeditor5 "42.0.2"
-    marked "4.0.12"
-    turndown "7.2.0"
-    turndown-plugin-gfm "1.0.2"
-
-"@ckeditor/ckeditor5-media-embed@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-media-embed/-/ckeditor5-media-embed-42.0.2.tgz"
-  integrity sha512-iXGcfgOm0IWa600ln5YeSssg7Sew6Lf1z9ziTxsQsmforPIqXgZQEvdLoo0tABddSRQZI+yQZnRnwrus9sZXIA==
-  dependencies:
-    "@ckeditor/ckeditor5-clipboard" "42.0.2"
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-typing" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-undo" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    "@ckeditor/ckeditor5-widget" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-mention@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-mention/-/ckeditor5-mention-42.0.2.tgz"
-  integrity sha512-81MYULfB7bHDb5Y7saIZMkNVG1BJV/ir5BwIDuuXwGXLNVX++uMTK4ryAItYToiSFN8/NBms7JFXPrRhL/zbOw==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-typing" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-minimap@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-minimap/-/ckeditor5-minimap-42.0.2.tgz"
-  integrity sha512-dOBT6bS/7tREFmpRCD4XwOEmoW4p7ZV1Pp3tA/KYQ++2BAgI/O/Yeww7nlhsKhal4r74v459hgihI/SnlfqBQA==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-page-break@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-page-break/-/ckeditor5-page-break-42.0.2.tgz"
-  integrity sha512-h6Wb0fWsl4a0MyU8W3F4Yku/1CWnR6tQrcMapn0sHB9W/HAvHLQIJGdsYh+a1W6QzMIjpVAqjT4mxQ1rU86RkQ==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-widget" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-paragraph@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-42.0.2.tgz"
-  integrity sha512-feI7Rw76uPbPmoFeVEPpKdPTOjdlccpWabhfrimgT08rECLa7ErFw2oRZVmnx5+kjX+NAUeD9kaUZUUkNNP0wg==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-
-"@ckeditor/ckeditor5-paste-from-office@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-paste-from-office/-/ckeditor5-paste-from-office-42.0.2.tgz"
-  integrity sha512-9K54E44rEjvLqWKRRHeifOlb1bICKzzX8gOv/i90sFQfMeQphA6qEn3WJZNQY4NY9Uwhu3kF/gh3/dqlcBhsvw==
-  dependencies:
-    "@ckeditor/ckeditor5-clipboard" "42.0.2"
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-remove-format@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-remove-format/-/ckeditor5-remove-format-42.0.2.tgz"
-  integrity sha512-YIyKibU44Jt6P9qu3WGPjUUh/pb5dvexeE1XG6f5JNtVlZCy3sUI+BDytzqWI68/coOHBKYkKSDOEQdzw83PdA==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-restricted-editing@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-restricted-editing/-/ckeditor5-restricted-editing-42.0.2.tgz"
-  integrity sha512-tfnEE6ieR2UhjZ9zoDNfXIMAMy2FWoajASKffdtpTMBjkVKzM+isg8j0hEkWgiQqCsJYVWt0314nPZrm5EUIfA==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-select-all@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-42.0.2.tgz"
-  integrity sha512-eqLhxmsxDQ8s+Op4f0OoXbN9vwz0hekE1HxsClXIsqwhjsO2o/HYcyhIzR9lPgmi4bVf8uy8T9oyWQNRLv4S9w==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-
-"@ckeditor/ckeditor5-show-blocks@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-show-blocks/-/ckeditor5-show-blocks-42.0.2.tgz"
-  integrity sha512-CFYJN3gyiWwJ1mDonzIktRL/A+WONZuyCptELqlU51RRCwbG7eSMtu2Eyd+Q463zYbOKZcdr5uNvlWuRpSsalw==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-source-editing@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-source-editing/-/ckeditor5-source-editing-42.0.2.tgz"
-  integrity sha512-lo/ZmBeAoWu9j0qfuUVIpc2QzZmcrYZ2enloz2mL22DCn3eP8IstE7gSmZlQ/DQxcPC5Sf2uC0l9IurBAP9+pg==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-theme-lark" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-special-characters@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-special-characters/-/ckeditor5-special-characters-42.0.2.tgz"
-  integrity sha512-B2E9thXW0Ej1istiResH6987g+REnX18aoxW4uXG+PHDrYWjsV4fClEnjWdkO/O0A3yOoNc4LYAbGSo7z0g/1g==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-typing" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-
-"@ckeditor/ckeditor5-style@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-style/-/ckeditor5-style-42.0.2.tgz"
-  integrity sha512-vq1GSeOtZm00W4FC6MgqukJbdDE394Sh7ID6634gKmdknbxOBvNcF0XUdAu+kWtJzTjYVrC4+oPYpS5C+odidQ==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-typing" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-table@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-table/-/ckeditor5-table-42.0.2.tgz"
-  integrity sha512-fFMXbQCa7UR4aAmwVkKzDcRmKCd2YwE1iNLeGWJz7tz1c+hGeadej0aHgUxBw+hHu6DhS9AyvtwmNweQpc3PnQ==
-  dependencies:
-    "@ckeditor/ckeditor5-clipboard" "42.0.2"
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    "@ckeditor/ckeditor5-widget" "42.0.2"
-    ckeditor5 "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-theme-lark@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-theme-lark/-/ckeditor5-theme-lark-42.0.2.tgz"
-  integrity sha512-t+/JVtK+lWzfLywsZX7eE8tfyBSnsaTsxeo84ZbSU9M1Vts5FN/5JExiY89VjsT8m84VAufbG+fDGjQpiYzsyg==
-  dependencies:
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-
-"@ckeditor/ckeditor5-typing@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-42.0.2.tgz"
-  integrity sha512-xwGazKjCJOQViGnk/Q0yVg98mc0aDJHvx6FsCFRF6e7B8WiMq8rPQjfO63TYOnUSOIkQJerbAv+hrsBS8XdxaQ==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-ui@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-42.0.2.tgz"
-  integrity sha512-Lrej61+xTTqIJSlA9FfqwpEClVoRabM3na8MDiWjAzneQkPgFtw1WTgUKvxNaI+eMXCmT/HVNj/RCg9vqt0pug==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    color-convert "2.0.1"
-    color-parse "1.4.2"
-    lodash-es "4.17.21"
-    vanilla-colorful "0.7.2"
-
-"@ckeditor/ckeditor5-undo@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-42.0.2.tgz"
-  integrity sha512-OpfdYnADY2MM8nWN5M13BEDDnwL15YHUYUpgMnydgJObZzSnePqgWQSFaBAY5j24eze0a8gyGgnOE5jV6VBm1Q==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-
-"@ckeditor/ckeditor5-upload@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-42.0.2.tgz"
-  integrity sha512-QD6PR1ZurGQv0gULG4hNiaFMO306qM9Gin2BbICkZuJ+IFKd7nQ+mp7ZCbgPgRYtSkeUyHjSzNR4+wIA2nPVEg==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-
-"@ckeditor/ckeditor5-utils@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-42.0.2.tgz"
-  integrity sha512-z4lNVoVf4cyK6cugMABNgMtYDiIK+0eQwYFtr45DhPK283RWEqrU0xwbwoqhIqeXRQ6B+9+0nC7ZIFPEdQ+iDA==
-  dependencies:
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-watchdog@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-42.0.2.tgz"
-  integrity sha512-0z00yqbBt/JALAD8C62LNySitQ+wBw1My43Qe2xs5VAP5tUZcziFFCc4BhMy+w6ZWUmZj2hkjSLlmx7b/vid+A==
-  dependencies:
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-widget@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-42.0.2.tgz"
-  integrity sha512-ZRI8H+Ir7YpByUO4/kKMNJJE5WUDoICl1BitSR9QKmkG7X2fBRdDG8setm4HsUU1kkPe0aYy6HK2ajZ2g5ZkaA==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-enter" "42.0.2"
-    "@ckeditor/ckeditor5-typing" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    lodash-es "4.17.21"
-
-"@ckeditor/ckeditor5-word-count@42.0.2":
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/@ckeditor/ckeditor5-word-count/-/ckeditor5-word-count-42.0.2.tgz"
-  integrity sha512-jtlyA6TXnnRpaTgvYG219z5p+MRZWUBz3r5oHa79lFcMDREZH6gKztiE+hYSmiL2OSAtHi0kYWUAF/oJfpHt3g==
-  dependencies:
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    ckeditor5 "42.0.2"
-    lodash-es "4.17.21"
-
-"@mixmark-io/domino@^2.2.0":
-  version "2.2.0"
-  resolved "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz"
-  integrity sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==
-
-blurhash@2.0.5:
-  version "2.0.5"
-  resolved "https://registry.npmjs.org/blurhash/-/blurhash-2.0.5.tgz"
-  integrity sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==
-
-ckeditor5@42.0.2:
-  version "42.0.2"
-  resolved "https://registry.npmjs.org/ckeditor5/-/ckeditor5-42.0.2.tgz"
-  integrity sha512-SHyyJ6y/+2Mas3SMlVchsq1i9LYqF7J7EMwEUKAt+sIXBW9pbBnLVncXpIpGTQ/M8fS20NVk7dfJ2P4TyEZGew==
-  dependencies:
-    "@ckeditor/ckeditor5-adapter-ckfinder" "42.0.2"
-    "@ckeditor/ckeditor5-alignment" "42.0.2"
-    "@ckeditor/ckeditor5-autoformat" "42.0.2"
-    "@ckeditor/ckeditor5-autosave" "42.0.2"
-    "@ckeditor/ckeditor5-basic-styles" "42.0.2"
-    "@ckeditor/ckeditor5-block-quote" "42.0.2"
-    "@ckeditor/ckeditor5-ckbox" "42.0.2"
-    "@ckeditor/ckeditor5-ckfinder" "42.0.2"
-    "@ckeditor/ckeditor5-clipboard" "42.0.2"
-    "@ckeditor/ckeditor5-cloud-services" "42.0.2"
-    "@ckeditor/ckeditor5-code-block" "42.0.2"
-    "@ckeditor/ckeditor5-core" "42.0.2"
-    "@ckeditor/ckeditor5-easy-image" "42.0.2"
-    "@ckeditor/ckeditor5-editor-balloon" "42.0.2"
-    "@ckeditor/ckeditor5-editor-classic" "42.0.2"
-    "@ckeditor/ckeditor5-editor-decoupled" "42.0.2"
-    "@ckeditor/ckeditor5-editor-inline" "42.0.2"
-    "@ckeditor/ckeditor5-editor-multi-root" "42.0.2"
-    "@ckeditor/ckeditor5-engine" "42.0.2"
-    "@ckeditor/ckeditor5-enter" "42.0.2"
-    "@ckeditor/ckeditor5-essentials" "42.0.2"
-    "@ckeditor/ckeditor5-find-and-replace" "42.0.2"
-    "@ckeditor/ckeditor5-font" "42.0.2"
-    "@ckeditor/ckeditor5-heading" "42.0.2"
-    "@ckeditor/ckeditor5-highlight" "42.0.2"
-    "@ckeditor/ckeditor5-horizontal-line" "42.0.2"
-    "@ckeditor/ckeditor5-html-embed" "42.0.2"
-    "@ckeditor/ckeditor5-html-support" "42.0.2"
-    "@ckeditor/ckeditor5-image" "42.0.2"
-    "@ckeditor/ckeditor5-indent" "42.0.2"
-    "@ckeditor/ckeditor5-language" "42.0.2"
-    "@ckeditor/ckeditor5-link" "42.0.2"
-    "@ckeditor/ckeditor5-list" "42.0.2"
-    "@ckeditor/ckeditor5-markdown-gfm" "42.0.2"
-    "@ckeditor/ckeditor5-media-embed" "42.0.2"
-    "@ckeditor/ckeditor5-mention" "42.0.2"
-    "@ckeditor/ckeditor5-minimap" "42.0.2"
-    "@ckeditor/ckeditor5-page-break" "42.0.2"
-    "@ckeditor/ckeditor5-paragraph" "42.0.2"
-    "@ckeditor/ckeditor5-paste-from-office" "42.0.2"
-    "@ckeditor/ckeditor5-remove-format" "42.0.2"
-    "@ckeditor/ckeditor5-restricted-editing" "42.0.2"
-    "@ckeditor/ckeditor5-select-all" "42.0.2"
-    "@ckeditor/ckeditor5-show-blocks" "42.0.2"
-    "@ckeditor/ckeditor5-source-editing" "42.0.2"
-    "@ckeditor/ckeditor5-special-characters" "42.0.2"
-    "@ckeditor/ckeditor5-style" "42.0.2"
-    "@ckeditor/ckeditor5-table" "42.0.2"
-    "@ckeditor/ckeditor5-theme-lark" "42.0.2"
-    "@ckeditor/ckeditor5-typing" "42.0.2"
-    "@ckeditor/ckeditor5-ui" "42.0.2"
-    "@ckeditor/ckeditor5-undo" "42.0.2"
-    "@ckeditor/ckeditor5-upload" "42.0.2"
-    "@ckeditor/ckeditor5-utils" "42.0.2"
-    "@ckeditor/ckeditor5-watchdog" "42.0.2"
-    "@ckeditor/ckeditor5-widget" "42.0.2"
-    "@ckeditor/ckeditor5-word-count" "42.0.2"
-
-color-convert@2.0.1:
-  version "2.0.1"
-  resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz"
-  integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
-  dependencies:
-    color-name "~1.1.4"
-
-color-name@^1.0.0, color-name@~1.1.4:
-  version "1.1.4"
-  resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
-  integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
-
-color-parse@1.4.2:
-  version "1.4.2"
-  resolved "https://registry.npmjs.org/color-parse/-/color-parse-1.4.2.tgz"
-  integrity sha512-RI7s49/8yqDj3fECFZjUI1Yi0z/Gq1py43oNJivAIIDSyJiOZLfYCRQEgn8HEVAj++PcRe8AnL2XF0fRJ3BTnA==
-  dependencies:
-    color-name "^1.0.0"
-
-lodash-es@4.17.21:
-  version "4.17.21"
-  resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz"
-  integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
-
-marked@4.0.12:
-  version "4.0.12"
-  resolved "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz"
-  integrity sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==
-
-turndown-plugin-gfm@1.0.2:
-  version "1.0.2"
-  resolved "https://registry.npmjs.org/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.2.tgz"
-  integrity sha512-vwz9tfvF7XN/jE0dGoBei3FXWuvll78ohzCZQuOb+ZjWrs3a0XhQVomJEb2Qh4VHTPNRO4GPZh0V7VRbiWwkRg==
-
-turndown@7.2.0:
-  version "7.2.0"
-  resolved "https://registry.npmjs.org/turndown/-/turndown-7.2.0.tgz"
-  integrity sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==
-  dependencies:
-    "@mixmark-io/domino" "^2.2.0"
-
-vanilla-colorful@0.7.2:
-  version "0.7.2"
-  resolved "https://registry.npmjs.org/vanilla-colorful/-/vanilla-colorful-0.7.2.tgz"
-  integrity sha512-z2YZusTFC6KnLERx1cgoIRX2CjPRP0W75N+3CC6gbvdX5Ch47rZkEMGO2Xnf+IEmi3RiFLxS18gayMA27iU7Kg==
+"@ckeditor/ckeditor5-clipboard@41.3.1":
+  "integrity" "sha512-6S7tq6FlnHYZmPACeqdf135Jx2bTKHVY8mHQ+CHC8ZZu0XVm62vVeeSLS2IcdtYmHjf4ced1G7suTUBHlfBCLw=="
+  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-41.3.1.tgz"
+  "version" "41.3.1"
+  dependencies:
+    "@ckeditor/ckeditor5-core" "41.3.1"
+    "@ckeditor/ckeditor5-engine" "41.3.1"
+    "@ckeditor/ckeditor5-ui" "41.3.1"
+    "@ckeditor/ckeditor5-utils" "41.3.1"
+    "@ckeditor/ckeditor5-widget" "41.3.1"
+    "lodash-es" "4.17.21"
+
+"@ckeditor/ckeditor5-core@41.3.1":
+  "integrity" "sha512-h+PgPtCpS2vjO3HbKMYtddRPW+B3AJx9qpixmHJnUZMiFCmRjUZjXATjpi3j+kSQISs4L2Yghq+lsAQxyGHb+A=="
+  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-41.3.1.tgz"
+  "version" "41.3.1"
+  dependencies:
+    "@ckeditor/ckeditor5-engine" "41.3.1"
+    "@ckeditor/ckeditor5-utils" "41.3.1"
+    "lodash-es" "4.17.21"
+
+"@ckeditor/ckeditor5-editor-inline@~41.3.1":
+  "integrity" "sha512-bAhs57qbeGT907yFsUUxdujtrNlmOTJK4DrBCsxoKSoSo8fcG4D05g/I4ehQp3A1CFYsF2Wkx58TtI/fwWRVbQ=="
+  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-inline/-/ckeditor5-editor-inline-41.3.1.tgz"
+  "version" "41.3.1"
+  dependencies:
+    "ckeditor5" "41.3.1"
+    "lodash-es" "4.17.21"
+
+"@ckeditor/ckeditor5-engine@41.3.1":
+  "integrity" "sha512-Me4cnkCrknDH50db/jPczuhgzaxUhHbkh2gv8N8Ypken9ZnOPvMD9W1gCFFTLaxikpPmBQwk3u1BSjOKk3r6kw=="
+  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-41.3.1.tgz"
+  "version" "41.3.1"
+  dependencies:
+    "@ckeditor/ckeditor5-utils" "41.3.1"
+    "lodash-es" "4.17.21"
+
+"@ckeditor/ckeditor5-enter@41.3.1":
+  "integrity" "sha512-iwhvJpfsutqcv/bf8QPMKhMolb7GtShaOT+UIDW3OXjMZaBKZOTyR8OceijwgBmZeillTaXQq9y2e9lbJd46xg=="
+  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-41.3.1.tgz"
+  "version" "41.3.1"
+  dependencies:
+    "@ckeditor/ckeditor5-core" "41.3.1"
+    "@ckeditor/ckeditor5-engine" "41.3.1"
+    "@ckeditor/ckeditor5-utils" "41.3.1"
+
+"@ckeditor/ckeditor5-paragraph@41.3.1":
+  "integrity" "sha512-weRPLyO/1Z8PpU9+lET4gYgJ8adDuCjYiREup81URSuS1DDQ8vb3D29xA+4Ov7lwg8BaNAMCpTBdp07GHHzv6w=="
+  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-41.3.1.tgz"
+  "version" "41.3.1"
+  dependencies:
+    "@ckeditor/ckeditor5-core" "41.3.1"
+    "@ckeditor/ckeditor5-ui" "41.3.1"
+    "@ckeditor/ckeditor5-utils" "41.3.1"
+
+"@ckeditor/ckeditor5-select-all@41.3.1":
+  "integrity" "sha512-a/LAPO+O9fwHjQ/8s3UNtyrqQRieAnpnPw2IhLlGqOS7nxPKMR2vkb6WnG2LUdO+wYqkCzxUDpBlfVkjkQEI0w=="
+  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-41.3.1.tgz"
+  "version" "41.3.1"
+  dependencies:
+    "@ckeditor/ckeditor5-core" "41.3.1"
+    "@ckeditor/ckeditor5-ui" "41.3.1"
+    "@ckeditor/ckeditor5-utils" "41.3.1"
+
+"@ckeditor/ckeditor5-typing@41.3.1":
+  "integrity" "sha512-4Oeafc3if6fTITOest1ILQ573fnkzE9/tn5eNm3zWnHVYR79mRCYxaha9yUlKVQiqaxZ48EVo2FjHiouXmn9+Q=="
+  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-41.3.1.tgz"
+  "version" "41.3.1"
+  dependencies:
+    "@ckeditor/ckeditor5-core" "41.3.1"
+    "@ckeditor/ckeditor5-engine" "41.3.1"
+    "@ckeditor/ckeditor5-utils" "41.3.1"
+    "lodash-es" "4.17.21"
+
+"@ckeditor/ckeditor5-ui@41.3.1":
+  "integrity" "sha512-xN7OAiRp7ALKYXUp6Qe/AjkjrhyLuoz9nxq7Jdsnsyb/XXfsXDloMcOuvNRoUgr4gIFHMOoZZxsIn8qegBvcYA=="
+  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-41.3.1.tgz"
+  "version" "41.3.1"
+  dependencies:
+    "@ckeditor/ckeditor5-core" "41.3.1"
+    "@ckeditor/ckeditor5-utils" "41.3.1"
+    "color-convert" "2.0.1"
+    "color-parse" "1.4.2"
+    "lodash-es" "4.17.21"
+    "vanilla-colorful" "0.7.2"
+
+"@ckeditor/ckeditor5-undo@41.3.1":
+  "integrity" "sha512-PElWTnlIwuQ94mvdhuH7Mno99oocSnOWPMHi9UuWe6+zVgznQwn0f0diBZvX3l5y8hFgK6q/pQ/CCmbvvYnovA=="
+  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-41.3.1.tgz"
+  "version" "41.3.1"
+  dependencies:
+    "@ckeditor/ckeditor5-core" "41.3.1"
+    "@ckeditor/ckeditor5-engine" "41.3.1"
+    "@ckeditor/ckeditor5-ui" "41.3.1"
+
+"@ckeditor/ckeditor5-upload@41.3.1":
+  "integrity" "sha512-ugTgGEgA9qsSl5+qptTmawdfYaONr6b3uTG4byZ76JMdf0qiniZjBF/TtGAVmBkCipcVWFoaZKteiz0fhQMHjA=="
+  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-41.3.1.tgz"
+  "version" "41.3.1"
+  dependencies:
+    "@ckeditor/ckeditor5-core" "41.3.1"
+    "@ckeditor/ckeditor5-utils" "41.3.1"
+
+"@ckeditor/ckeditor5-utils@41.3.1":
+  "integrity" "sha512-jJu9ndn6Y7+ffBYdDCRXX7OnV9Ddgms2HSF1pmhjZN0uoL96XworuUOn8hx3Zs/KBPjJEwbtYWJMjG9aohrgaQ=="
+  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-41.3.1.tgz"
+  "version" "41.3.1"
+  dependencies:
+    "lodash-es" "4.17.21"
+
+"@ckeditor/ckeditor5-watchdog@41.3.1":
+  "integrity" "sha512-iDwdYxC8euSKxfRq4y5vVOX9GVUbEbC9z6glkXpxa1BogqYh39+fywjt+s4o3Ub3b8FJ/EUYuNc+/vK+CzEg4g=="
+  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-41.3.1.tgz"
+  "version" "41.3.1"
+  dependencies:
+    "lodash-es" "4.17.21"
+
+"@ckeditor/ckeditor5-widget@41.3.1":
+  "integrity" "sha512-rdBxGS3bxWNhp+yxyBYkcbRV6/mdTDab+konDVhZ/ME1jVZ5cf8OBZcgHUqAxzuWt4XMEdzKINbo1OnSDwApUg=="
+  "resolved" "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-41.3.1.tgz"
+  "version" "41.3.1"
+  dependencies:
+    "@ckeditor/ckeditor5-core" "41.3.1"
+    "@ckeditor/ckeditor5-engine" "41.3.1"
+    "@ckeditor/ckeditor5-enter" "41.3.1"
+    "@ckeditor/ckeditor5-typing" "41.3.1"
+    "@ckeditor/ckeditor5-ui" "41.3.1"
+    "@ckeditor/ckeditor5-utils" "41.3.1"
+    "lodash-es" "4.17.21"
+
+"ckeditor5@41.3.1":
+  "integrity" "sha512-pBK1YZV9Sy4R53XG70TEeLFOvTFC7tg8AmS6d6zizegtwkH8seblkcERkykcNuvmfzZ/2h9JbafJ4kisZOwiUQ=="
+  "resolved" "https://registry.npmjs.org/ckeditor5/-/ckeditor5-41.3.1.tgz"
+  "version" "41.3.1"
+  dependencies:
+    "@ckeditor/ckeditor5-clipboard" "41.3.1"
+    "@ckeditor/ckeditor5-core" "41.3.1"
+    "@ckeditor/ckeditor5-engine" "41.3.1"
+    "@ckeditor/ckeditor5-enter" "41.3.1"
+    "@ckeditor/ckeditor5-paragraph" "41.3.1"
+    "@ckeditor/ckeditor5-select-all" "41.3.1"
+    "@ckeditor/ckeditor5-typing" "41.3.1"
+    "@ckeditor/ckeditor5-ui" "41.3.1"
+    "@ckeditor/ckeditor5-undo" "41.3.1"
+    "@ckeditor/ckeditor5-upload" "41.3.1"
+    "@ckeditor/ckeditor5-utils" "41.3.1"
+    "@ckeditor/ckeditor5-watchdog" "41.3.1"
+    "@ckeditor/ckeditor5-widget" "41.3.1"
+
+"color-convert@2.0.1":
+  "integrity" "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="
+  "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz"
+  "version" "2.0.1"
+  dependencies:
+    "color-name" "~1.1.4"
+
+"color-name@^1.0.0", "color-name@~1.1.4":
+  "integrity" "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+  "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
+  "version" "1.1.4"
+
+"color-parse@1.4.2":
+  "integrity" "sha512-RI7s49/8yqDj3fECFZjUI1Yi0z/Gq1py43oNJivAIIDSyJiOZLfYCRQEgn8HEVAj++PcRe8AnL2XF0fRJ3BTnA=="
+  "resolved" "https://registry.npmjs.org/color-parse/-/color-parse-1.4.2.tgz"
+  "version" "1.4.2"
+  dependencies:
+    "color-name" "^1.0.0"
+
+"lodash-es@4.17.21":
+  "integrity" "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
+  "resolved" "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz"
+  "version" "4.17.21"
+
+"vanilla-colorful@0.7.2":
+  "integrity" "sha512-z2YZusTFC6KnLERx1cgoIRX2CjPRP0W75N+3CC6gbvdX5Ch47rZkEMGO2Xnf+IEmi3RiFLxS18gayMA27iU7Kg=="
+  "resolved" "https://registry.npmjs.org/vanilla-colorful/-/vanilla-colorful-0.7.2.tgz"
+  "version" "0.7.2"
-- 
GitLab


From 30a7b1d795dec11d9db41cca22fe73d116d1f5ff Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Wed, 18 Sep 2024 13:16:38 -0700
Subject: [PATCH 16/33] Use the view mode to discern what fields to hide/show
 in the sidebar.

---
 css/edit-plus.css                              |  9 ++++-----
 js/edit_plus/entity-form.js                    | 14 ++++----------
 src/EventSubscriber/DefaultFieldAttributes.php | 11 ++++++++++-
 3 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/css/edit-plus.css b/css/edit-plus.css
index f06a29c..8a5773e 100644
--- a/css/edit-plus.css
+++ b/css/edit-plus.css
@@ -40,13 +40,12 @@ div.edit-plus-hidden {
   display: none;
 }
 
-[data-edit-plus-id] {
-
-  &:has(> .ajax-progress) {
-    position: relative;
-  }
+/* AJAX throbber */
+.disabled-updating {
+  position: relative;
 
   .ajax-progress {
+    user-select: none;
     position: absolute;
     top: 0;
     bottom: 0;
diff --git a/js/edit_plus/entity-form.js b/js/edit_plus/entity-form.js
index 1c161ac..6b33394 100644
--- a/js/edit_plus/entity-form.js
+++ b/js/edit_plus/entity-form.js
@@ -194,21 +194,15 @@ export const updateTempstore = (EditableElement, isEmpty, form = null) => {
     // when it's available as it's a tiny bit faster.
     viewMode = EditableElement.info.viewMode;
 
-    // Add an AJAX throbber to indicate the item is being updated.
     const pageElementHandle = EditableElement.getPageElementHandle();
+    // Disable editing the item while it's being updated.
+    pageElementHandle.classList.add('disabled-updating');
+    // Add an AJAX throbber to indicate the item is being updated.
     const throbber = Drupal.theme.ajaxProgressThrobber(Drupal.t('Updating...'));
     pageElementHandle.insertAdjacentHTML('beforeend', throbber);
     setTimeout(() => {
-      document.querySelector('[data-edit-plus-id] .ajax-progress').classList.add('background-fade-in');
+      document.querySelector('[data-edit-plus-field-value-wrapper] .ajax-progress').classList.add('background-fade-in');
     }, 50);
-    // Disable the item while it's being updated.
-    const disable = element => {
-      element.classList.add('disabled-updating');
-    };
-    if (pageElementHandle.classList.contains('edit-plus-field-value')) {
-      disable(pageElementHandle);
-    }
-    pageElementHandle.querySelector('.edit-plus-field-value')?.forEach(disable);
 
   } else {
     // EditableElement won't be available when submitting the form via EditPlusEntityFormAutoSave.
diff --git a/src/EventSubscriber/DefaultFieldAttributes.php b/src/EventSubscriber/DefaultFieldAttributes.php
index 334d5d4..034761f 100644
--- a/src/EventSubscriber/DefaultFieldAttributes.php
+++ b/src/EventSubscriber/DefaultFieldAttributes.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
 
 namespace Drupal\edit_plus\EventSubscriber;
 
+use Drupal\Core\Entity\Entity\EntityViewDisplay;
 use Drupal\Core\Render\Element;
 use Drupal\Core\Template\Attribute;
 use Drupal\Core\Entity\EntityInterface;
@@ -36,7 +37,15 @@ class DefaultFieldAttributes implements EventSubscriberInterface {
     $form_item['#attributes']['data-edit-plus-form-item-wrapper-id'] = sprintf('%s::%s::%s::%s', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity), $field_name, 'value');
     $form_item['#attributes']['data-edit-plus-form-item-widget'] = self::getWidget($event);
     $form_item['#attributes']['class'][] = 'edit-plus-form-item-wrapper';
-    $form_item['#attributes']['class'][] = 'edit-plus-hidden';
+
+    $display = EntityViewDisplay::collectRenderDisplay($entity, $event->getViewMode())->toArray();
+    if (empty($display['hidden'][$field_name])) {
+      // Hide form items of elements that will be edited inline.
+//      $form_item['#attributes']['class'][] = 'edit-plus-hidden';
+    } else {
+      // If the field is hidden in the view mode, it can't be edited inline.
+      $form_item['#attributes']['data-edit-plus-auto-submit'] = '';
+    }
 
     $event->setForm($form);
   }
-- 
GitLab


From 26e90541c323a287be0d01a63b00965eec17e8b8 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Wed, 18 Sep 2024 17:06:48 -0700
Subject: [PATCH 17/33] Switch from clone form item to position form item.

---
 README.md                                     |   9 +
 css/ckeditor.css                              |   8 +
 css/edit-plus.css                             |  10 +-
 edit_plus.services.yml                        |   3 -
 js/edit_plus/editable-element.js              |  11 -
 js/edit_plus/entity-form.js                   |  52 +++-
 js/edit_plus/fields/default.js                |   6 +-
 js/edit_plus/fields/field-plugin-base.js      | 288 ++++--------------
 js/edit_plus/fields/inline-editor.js          |  11 +-
 js/edit_plus/fields/media.js                  |   2 -
 js/edit_plus/utilities.js                     |  32 --
 src/EventSubscriber/CloneFieldAttribute.php   |  74 -----
 .../DefaultFieldAttributes.php                |   2 +-
 src/EventSubscriber/MediaFieldAttributes.php  |   1 -
 src/Form/FieldConfigFormAlter.php             |  15 -
 15 files changed, 142 insertions(+), 382 deletions(-)
 delete mode 100644 src/EventSubscriber/CloneFieldAttribute.php

diff --git a/README.md b/README.md
index 2d266ac..d041e86 100644
--- a/README.md
+++ b/README.md
@@ -14,3 +14,12 @@ To relate the above editable page element to the form item that was loaded when
 ```html
 <!-- @todo 😅 -->
 ```
+
+
+### Inline Editing z-index
+If the inline editing z-index is undesirable for your theme override it with. Since the inline editor is visually moved out of the sidebar, it inherits whatever the sidebar z-index is.
+```html
+.toolbar-plus-sidebar {
+  z-index: 2;
+}
+```
diff --git a/css/ckeditor.css b/css/ckeditor.css
index 36c57b9..104bd78 100644
--- a/css/ckeditor.css
+++ b/css/ckeditor.css
@@ -10,3 +10,11 @@
 :not(form) .edit-plus-inline-edit.ck.ck-blurred > :last-child {
   margin-top: inherit;
 }
+
+.edit-plus-form-item .ck-content {
+  min-height: auto;
+}
+
+.ck-body-wrapper .ck.ck-balloon-panel {
+  z-index: 2;
+}
diff --git a/css/edit-plus.css b/css/edit-plus.css
index 8a5773e..1c9b078 100644
--- a/css/edit-plus.css
+++ b/css/edit-plus.css
@@ -1,8 +1,12 @@
 .edit-plus-hidden,
 input.edit-plus-hidden,
 div.edit-plus-hidden {
-  visibility: hidden !important;
+  visibility: hidden;
   position: absolute;
+  /* Reveal elements being edited */
+  .edit-plus-editing {
+    visibility: visible;
+  }
 }
 
 #edit_plus {
@@ -16,6 +20,10 @@ div.edit-plus-hidden {
   color: #000;
 }
 
+#sized-placeholder {
+  width: auto;
+}
+
 .ck-powered-by-balloon * {
   display: none;
 }
diff --git a/edit_plus.services.yml b/edit_plus.services.yml
index 68d51d4..db7abcb 100644
--- a/edit_plus.services.yml
+++ b/edit_plus.services.yml
@@ -45,6 +45,3 @@ services:
 
   edit_plus.event_subscriber.media_field_attributes:
     class: Drupal\edit_plus\EventSubscriber\MediaFieldAttributes
-
-  edit_plus.event_subscriber.clone_field_attribute:
-    class: Drupal\edit_plus\EventSubscriber\CloneFieldAttribute
diff --git a/js/edit_plus/editable-element.js b/js/edit_plus/editable-element.js
index 4942ae5..66bda6d 100644
--- a/js/edit_plus/editable-element.js
+++ b/js/edit_plus/editable-element.js
@@ -117,17 +117,6 @@ export class EditableElement {
     return document.querySelector('[data-form-item-placeholder="' + util.getFormItemWrapperId(this.info) + '"]');
   }
 
-  /**
-   * Is cloneable.
-   *
-   * @returns {boolean}
-   *   Whether this field has been configured to swap a clone or the actual
-   *   form item into the page for editing.
-   */
-  isCloneable() {
-    return this.getFormItemWrapper().dataset.editPlusClone === 'true';
-  }
-
   /**
    * Handle is wrapper.
    *
diff --git a/js/edit_plus/entity-form.js b/js/edit_plus/entity-form.js
index 6b33394..da60c30 100644
--- a/js/edit_plus/entity-form.js
+++ b/js/edit_plus/entity-form.js
@@ -194,14 +194,14 @@ export const updateTempstore = (EditableElement, isEmpty, form = null) => {
     // when it's available as it's a tiny bit faster.
     viewMode = EditableElement.info.viewMode;
 
-    const pageElementHandle = EditableElement.getPageElementHandle();
+    const pageElementWrapper = EditableElement.getPageElementWrapper();
     // Disable editing the item while it's being updated.
-    pageElementHandle.classList.add('disabled-updating');
+    pageElementWrapper.classList.add('disabled-updating');
     // Add an AJAX throbber to indicate the item is being updated.
     const throbber = Drupal.theme.ajaxProgressThrobber(Drupal.t('Updating...'));
-    pageElementHandle.insertAdjacentHTML('beforeend', throbber);
+    pageElementWrapper.insertAdjacentHTML('beforeend', throbber);
     setTimeout(() => {
-      document.querySelector('[data-edit-plus-field-value-wrapper] .ajax-progress').classList.add('background-fade-in');
+      document.querySelector('.disabled-updating .ajax-progress')?.classList.add('background-fade-in');
     }, 50);
 
   } else {
@@ -223,6 +223,45 @@ jQuery.fn.editPlusIsDoneUpdating = () => {
   editPlusIsUpdating = false;
 };
 
+/**
+ * Edit plus update markup
+ *
+ * This is an AJAX method called after updating the tempstore.
+ */
+jQuery.fn.EditPlusUpdateMarkup = (selector, content) => {
+  if (Drupal.EditPlus.CurrentlyEditingElement) {
+    // @todo Add a "save controller" that tracks when a save needs to happen to
+    // @todo avoid unnecessary saves.
+    // Say a property was changed in the sidebar, if an element is still being
+    // edited, there's no reason to save yet as there is no element on the page
+    // to update. We could just return; here and wait till the formItem is
+    // finished being updated, but the formItem might not have changes. We need
+    // to track that a save needs to occur, collect all the changes then
+    // submit them when the pageElement needs a render.
+  }
+  if (Drupal.EditPlus.onlyUpdateElement) {
+    // The user made changes to one form item then clicked another editable
+    // element > the next editable element was focused, the tempstore recorded the
+    // change and returned the updated page markup > let's now update only the
+    // first element that had its values recorded in the tempstore. If we were to
+    // update the whole page at this point the actively focused form element
+    // would be removed.
+    const contentElement = document.createElement('div');
+    contentElement.innerHTML = content;
+    const elementToUpdateId = Drupal.EditPlus.onlyUpdateElement.getPageElementWrapper().dataset.editPlusFieldValueWrapper;
+    const elementToUpdateSelector = '[data-edit-plus-field-value-wrapper="' + elementToUpdateId + '"]';
+    const updatedElement = contentElement.querySelector(elementToUpdateSelector);
+    const element = document.querySelector(elementToUpdateSelector);
+    element.replaceWith(updatedElement)
+    Drupal.EditPlus.onlyUpdateElement = null;
+  } else {
+    // Update/replace the whole thing.
+    const entityWrapper = document.querySelector(selector);
+    entityWrapper.outerHTML = content;
+  }
+  Drupal.EditPlus.EnableEditMode();
+}
+
 (($, Drupal, once) => {
 
   /**
@@ -234,6 +273,11 @@ jQuery.fn.editPlusIsDoneUpdating = () => {
     attach: (context, settings) => {
       once('EditPlusEntityFormAutoSave', '[data-edit-plus-auto-submit]', context).forEach(formItem => {
         formItem.addEventListener('change', e => {
+          // Don't update the page as it's still being edited since it's hidden
+          // and will have to be updated again anyways.
+          if (Drupal.EditPlus.CurrentlyEditingElement) {
+            return;
+          }
           updateTempstore(null, false, e.target.closest('form'));
         });
       });
diff --git a/js/edit_plus/fields/default.js b/js/edit_plus/fields/default.js
index 91e3921..7cada5c 100644
--- a/js/edit_plus/fields/default.js
+++ b/js/edit_plus/fields/default.js
@@ -41,9 +41,9 @@ export class DefaultPlugin extends fieldPluginBase.FieldPluginBase {
     else {
       let values = {};
       for (let i=0; i < inputs.length; i++) {
-        if (inputs[i].value) {
-          values[i] = inputs[i].value;
-        }
+        values[i] = inputs[i].hasAttribute('data-ckeditor5-id') && Drupal.CKEditor5Instances.get(inputs[i].dataset.ckeditor5Id)
+          ? Drupal.CKEditor5Instances.get(inputs[i].dataset.ckeditor5Id).getData()
+          : inputs[i].value;
       }
       return values;
     }
diff --git a/js/edit_plus/fields/field-plugin-base.js b/js/edit_plus/fields/field-plugin-base.js
index ad88d86..4c13c23 100644
--- a/js/edit_plus/fields/field-plugin-base.js
+++ b/js/edit_plus/fields/field-plugin-base.js
@@ -1,4 +1,3 @@
-import * as editableElement from '../editable-element.js';
 
 /**
  * Field plugin base.
@@ -8,9 +7,7 @@ import * as editableElement from '../editable-element.js';
 export class FieldPluginBase {
 
   constructor() {
-    this.isObserverActive = false;
     this.originalValue = null;
-    this.clonedElement = null;
   }
 
   init() {}
@@ -44,10 +41,12 @@ export class FieldPluginBase {
    *   The element being edited.
    */
   focus(EditableElement) {
-    // Prepare for de-focusing the form item. It would be easy to add a
-    // formItem.onblur when the form item looses focus, but losing focus on the
-    // form item doesn't necessarily mean we are done with it. e.g. changing a
-    // text format in the sidebar.
+    // Prepare for the eventual de-focusing the form item. It would be easy to
+    // add a formItem.onblur when the form item looses focus, but losing focus
+    // on the form item doesn't necessarily mean we are done with it. e.g.
+    // changing a text format in the sidebar. Let's keep track of what is
+    // currently focused so that we can check if one of its ancillary elements
+    // was clicked.
     EditableElement.getFormItemWrapper().classList.add('edit-plus-focused');
     Drupal.EditPlus.Focused = {
       formItem: EditableElement.getFormItemHandle(),
@@ -67,6 +66,7 @@ export class FieldPluginBase {
    * instructions on how to give the element focus.
    *
    * @param EditableElement
+   *   The element being edited.
    *
    * @param event
    */
@@ -100,14 +100,6 @@ export class FieldPluginBase {
       // Only update the page with the item that was just changed.
       Drupal.EditPlus.onlyUpdateElement = Drupal.EditPlus.Focused.editableElement;
 
-      // @todo Can we just always only update the thing that was changed?
-      // const fieldValue = e.target.closest('.edit-plus-field-value');
-      // if (fieldValue) {
-      //   // We lost focus when clicking another editable element. Only update the
-      //   // rendered page with the last changed element.
-      //   Drupal.EditPlus.onlyUpdateElement = Drupal.EditPlus.Focused.editableElement;
-      // }
-
       plugin.blur();
       document.querySelectorAll('.edit-plus-focused').forEach(element => {
         element.classList.remove('edit-plus-focused');
@@ -122,10 +114,6 @@ export class FieldPluginBase {
    */
   blur() {
     const EditableElement = Drupal.EditPlus.Focused.editableElement;
-    if (Drupal.EditPlus.Focused.editableElement.isCloneable()) {
-      this.isObserverActive = false;
-      this.observer.disconnect();
-    }
     document.removeEventListener('mousedown', this.watchFocus, true);
     Drupal.EditPlus.Focused = null;
     this.blurElement(EditableElement);
@@ -166,197 +154,60 @@ export class FieldPluginBase {
     EditableElement.getFormItemWrapper().classList.add('edit-plus-hidden');
   }
 
-
   /**
-   * Replace page markup with editable element.
-   *
-   * Moves a form item from the form to the main page area. Users can configure
-   * whether the actual form item is swapped for the rendered element on the page
-   * or a clone of the form item. Some form items like media libraries stop
-   * working when taken out of the form. In that case a clone is created and the
-   * clicks on the clone are forwarded to the original form item.
-   *
-   * @param EditableElement
-   *   The element being edited.
-   */
-  replacePageMarkupWithEditableElement(EditableElement) {
-    if (EditableElement.isCloneable()) {
-      this.replacePageMarkupWithClonedFormItem(EditableElement);
-    } else {
-      this.replacePageMarkupWithFormItem(EditableElement);
-    }
-  }
-
-  /**
-   * Replace page markup with form item.
-   *
-   * @param EditableElement
-   *   The element being edited.
+   * Position editable element over page element.
    */
-  replacePageMarkupWithFormItem(EditableElement) {
-    const pageElementHandle = EditableElement.getPageElementHandle();
-    const formItemWrapper = EditableElement.getFormItemWrapper();
-    const formElementHandle = EditableElement.getFormItemHandle();
-    const placeMarker = document.createElement('div');
-    placeMarker.dataset.formItemPlaceholder = formItemWrapper.dataset.editPlusFormItemWrapperId;
-    formElementHandle.parentNode.insertBefore(placeMarker, formElementHandle);
-    pageElementHandle.classList.add('edit-plus-hidden');
-    pageElementHandle.parentNode.insertBefore(formElementHandle, pageElementHandle)
-    formElementHandle.appendChild(pageElementHandle);
-    formElementHandle.classList.remove('edit-plus-hidden');
-    formElementHandle.classList.add('edit-plus-focused');
+  positionEditableElementOverPageElement() {
+    const EditableElement = Drupal.EditPlus.CurrentlyEditingElement;
+    const formItem = EditableElement.getFormItemHandle();
+    const rectangle = document.querySelector('#sized-placeholder').getBoundingClientRect();
+
+    formItem.style.position = 'fixed';
+    formItem.style.left = `${rectangle.left}px`;
+    formItem.style.top = `${rectangle.top}px`;
+    formItem.style.width = `${rectangle.width}px`;
   }
 
   /**
-   * Replace page markup with cloned form item.
+   * Replace page markup with editable element.
    *
-   * @param EditableElement
-   *   The element being edited.
-   */
-  replacePageMarkupWithClonedFormItem(EditableElement) {
-    this.isObserverActive = true;
-
-    const pageElementHandle = EditableElement.getPageElementHandle();
-    pageElementHandle.classList.add('edit-plus-hidden');
-
-    const clone = this.cloneElement(EditableElement);
-    pageElementHandle.parentNode.insertBefore(clone, pageElementHandle);
-    clone.classList.remove('edit-plus-hidden');
-  }
-
-  /**
-   * Clone element.
+   * Visually moves a form item from the form in the sidebar over the editable
+   * element that was clicked in the main page area.
    *
    * @param EditableElement
    *   The element being edited.
-   *
-   * @returns {Node}
-   *   A clone of the EditableElement form item's handle.
    */
-  cloneElement(EditableElement) {
-    const formElementHandle = EditableElement.getFormItemHandle();
-    // Remove old clones.
-    document.querySelectorAll('#' + this.getClonedElementId(formElementHandle)).forEach(clone => {
-      clone.remove();
-    });
-    // Make a clone of the form item formElementHandle which will be placed in the page for
-    // editing.
-    const clone = formElementHandle.cloneNode(true);
-    // Make an additional clone to remember the current state of the element to
-    // later detect if any AJAX changes have occurred to the original form item
-    // so that we can only update the page when necessary.
-    this.clonedElement = formElementHandle.cloneNode(true);
-
-    // Prepare the cloned form element for being placed on the page by tweaking
-    // its attributes so the clone is no longer a duplicate of the form item
-    // which might confuse JS.
-    clone.id = this.getClonedElementId(clone);
-    clone.classList.add('edit-plus-clone');
-    clone.setAttribute('data-edit-plus-clone-id', 'handle');
-    const handleChildren = formElementHandle.querySelectorAll('*');
-    const cloneChildren = clone.querySelectorAll('*');
-    handleChildren.forEach((element, index) => {
-      // Identify it as a clone.
-      if (element.id) {
-        cloneChildren[index].id = this.getClonedElementId(element);
-      }
-
-      // Ensure we have unique ID's for every div that correlates it back to the
-      // original so we can transfer clicks from the clone back to the original.
-      if (element.hasAttribute('data-edit-plus-original-id')) {
-        element.removeAttribute('data-edit-plus-original-id');
-      }
-      element.setAttribute('data-edit-plus-original-id', index);
-      cloneChildren[index].setAttribute('data-edit-plus-clone-id', index);
-
-      // Remove any cloned fadeIn's.
-      if (element.style.opacity) {
-        element.style.opacity = '';
-      }
-    });
+  replacePageMarkupWithEditableElement(EditableElement) {
+    Drupal.EditPlus.CurrentlyEditingElement = EditableElement;
 
-    // Transfer events on the cloned element (clicks, drags, input, etc) to the
-    // original form element.
-    Object.keys(window).forEach(key => {
-      if (/^on(?!animationiteration|animationstart|mouseenter|mouseout|mouseevent|mousemove|mouseover|mouseleave|mousein|pointerenter|pointerleave|pointerout|pointerup|pointermove|pointerrawupdate|pointerover|pointerdown|transitionrun|transitionstart|transitioncancel|transitionend|scroll|scrollend)/.test(key)) {
-        clone.addEventListener(key.slice(2), e => {
-          const cloneId = e.target?.dataset?.editPlusCloneId ?? false;
-          if (!cloneId) {
-            return;
-          }
-          const originalFormElement = this.getOriginalFromClone(cloneId);
-          if (e.type === 'input') {
-            // Transfer input changes.
-            const clonedInput = e.target;
-            const originalInput = this.getOriginalFromClone(clonedInput.dataset.editPlusCloneId);
-            // If the event is a select list change. Update the selected
-            // attribute so that when it is cloned again the selected option persists.
-            if (clonedInput.nodeName === 'SELECT') {
-              originalInput[originalInput.selectedIndex].removeAttribute('selected');
-              originalInput[clonedInput.selectedIndex].setAttribute('selected', 'selected');
-            }
-            originalInput.value = clonedInput.value;
-          } else {
-            // Transfer any other events.
-            const forwardEvent = jQuery.Event(e.type);
-            forwardEvent.originalEvent = e;
-            jQuery(originalFormElement).trigger(forwardEvent);
-          }
-        });
-      }
-    });
+    const pageElement = EditableElement.getPageElementHandle();
+    const formItem = EditableElement.getFormItemHandle();
+    const sizedPlaceholder = document.createElement('div');
 
-    clone.dataset.editPlusClone = formElementHandle.dataset.editPlusFormItemWrapperId;
+    // Add an element that the form item will hover over.
+    sizedPlaceholder.id = 'sized-placeholder';
+    pageElement.parentElement.insertBefore(sizedPlaceholder, pageElement);
 
-    // Pass along the Edit+ ID so recreate EditableElement as changes occur
-    formElementHandle.dataset.editPlusPageElementEditPlusId = EditableElement.getPageElement().dataset.editPlusId;
+    this.positionEditableElementOverPageElement();
 
-    // Watch for changes to the original element.
-    this.observer = new MutationObserver((mutations) => {
-      if (!this.isObserverActive) {
-        return;
-      }
-      const EditableElement = editableElement.EditableElement.createFromFormItem(mutations[0].target);
+    // Update the form item's position on scroll and window resize.
+    document.addEventListener('scroll', this.positionEditableElementOverPageElement);
+    window.addEventListener('resize', this.positionEditableElementOverPageElement);
 
-      // Update the clone if there has been changes to the form element.
-      if (this.clonedElement.outerHTML !== EditableElement.getFormItemHandle().outerHTML) {
-        this.replacePageMarkupWithEditableElement(EditableElement);
+    // Ensure the sizedPlaceholder height stays in sync with the formItem height.
+    // As items are added or removed from the form item via ajax, the sizedPlaceholder
+    // show grow or shrink accordingly.
+    Drupal.EditPlus.CurrentlyEditingElement.sizedPlaceholderHeightObserver = new ResizeObserver(entries => {
+      const sizedPlaceholder = document.querySelector('#sized-placeholder');
+      for (let entry of entries) {
+        sizedPlaceholder.style.height = entry.contentRect.height + 'px';
       }
     });
-    this.observer.observe(formElementHandle, {
-      attributes: true,
-      attributeFilter: ['checked'],
-      childList: true,
-      subtree: true,
-    });
+    Drupal.EditPlus.CurrentlyEditingElement.sizedPlaceholderHeightObserver.observe(formItem);
 
-    // Mutation observers can't detect checkboxes. Watch for those changes explicitly.
-    formElementHandle.querySelectorAll('input[type="checkbox"]').forEach(checkbox => {
-      checkbox.addEventListener('change', e => {
-        const EditableElement = editableElement.EditableElement.createFromFormItem(e.target);
-        this.replacePageMarkupWithEditableElement(EditableElement);
-      });
-    });
-
-    return clone;
-  }
-
-
-  getOriginalFromClone(cloneId) {
-    return document.querySelector('[data-edit-plus-original-id="' + cloneId + '"]');
-  }
-
-  /**
-   * Get cloned element ID.
-   *
-   * @param element
-   *  A div with an ID inside the form item handle being cloned.
-   *
-   * @returns {string}
-   *   An edit plus cloned + id string.
-   */
-  getClonedElementId(element) {
-    return 'edit-plus-cloned_' + element.id;
+    pageElement.classList.add('edit-plus-hidden');
+    formItem.classList.add('edit-plus-editing');
+    formItem.classList.remove('edit-plus-hidden');
   }
 
   /**
@@ -368,48 +219,21 @@ export class FieldPluginBase {
    *   The element being edited.
    */
   replaceEditableElementWithMarkup(EditableElement) {
-    if (EditableElement.isCloneable()) {
-      this.replaceClonedFormItemWithPageElement(EditableElement);
-    } else {
-      this.replaceFormItemWithPageElement(EditableElement);
-    }
-  }
+    document.removeEventListener('scroll', this.positionEditableElementOverPageElement);
+    window.removeEventListener('resize', this.positionEditableElementOverPageElement);
+    Drupal.EditPlus.CurrentlyEditingElement.sizedPlaceholderHeightObserver.disconnect();
+    delete Drupal.EditPlus.CurrentlyEditingElement.sizedPlaceholderHeightObserver;
+    delete Drupal.EditPlus.CurrentlyEditingElement;
 
-  /**
-   * Replace cloned form item with page element.
-   *
-   * @param EditableElement
-   *   The element being edited.
-   */
-  replaceClonedFormItemWithPageElement(EditableElement) {
-    const formElementHandle = EditableElement.getFormItemHandle();
+    const pageElement = EditableElement.getPageElementHandle();
+    const formItem = EditableElement.getFormItemHandle();
 
-    // Remove old clones.
-    document.querySelectorAll('#' + this.getClonedElementId(formElementHandle)).forEach(clone => {
-      clone.remove();
-    });
-    // Remove binding attribute.
-    document.querySelectorAll('[data-edit-plus-original-id]').forEach(element => {
-      element.removeAttribute('data-edit-plus-original-id');
-    })
-    EditableElement.getPageElementHandle().classList.remove('edit-plus-hidden')
-  }
+    formItem.removeAttribute('style');
+    formItem.classList.remove('edit-plus-editing');
+    document.querySelector('#sized-placeholder').remove();
 
-  /**
-   *  Replace form item with page element.
-   *
-   * @param EditableElement
-   *   The element being edited.
-   */
-  replaceFormItemWithPageElement(EditableElement) {
-    const pageElementHandle = EditableElement.getPageElementHandle();
-    const placeMarker = EditableElement.getFormPlaceMarker();
-    const formElementHandle = EditableElement.getFormItemHandle();
-    formElementHandle.parentNode.insertBefore(pageElementHandle, formElementHandle);
-    placeMarker.parentNode.insertBefore(formElementHandle, placeMarker);
-    pageElementHandle.classList.remove('edit-plus-hidden')
-    placeMarker.remove();
-    Drupal.EditPlus.FieldPluginManager.getPlugin(EditableElement).hideAncillary(EditableElement);
+    formItem.classList.add('edit-plus-hidden');
+    pageElement.classList.remove('edit-plus-hidden');
   }
 
   /**
@@ -427,7 +251,7 @@ export class FieldPluginBase {
   getFocusedSelectors() {
     return [
       '.edit-plus-focused',
-      '[data-edit-plus-clone]',
+      '#toolbar-plus-sidebar',
     ];
   }
 
diff --git a/js/edit_plus/fields/inline-editor.js b/js/edit_plus/fields/inline-editor.js
index f35c561..ebaff0c 100644
--- a/js/edit_plus/fields/inline-editor.js
+++ b/js/edit_plus/fields/inline-editor.js
@@ -1,4 +1,3 @@
-import * as util from '../utilities.js';
 import * as entityForm from '../entity-form.js';
 import * as fieldPluginBase from './field-plugin-base.js';
 import * as editableElement from '../editable-element.js';
@@ -37,7 +36,9 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
       if (ckeditor5Id) {
         const editor = Drupal.EditPlus.Ckeditor5Instances.get(ckeditor5Id);
         if (editor) {
-          editor.focus();
+          setTimeout(() => {
+            editor.focus();
+          }, 0);
         } else {
           // The editor hasn't been built yet because the form was just loaded.
           // Remember that this element needs focus and focus it after the editor
@@ -232,12 +233,16 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
 
         // Process the field formatter config.
         const { editorInline } = CKEditor5;
-        const {
+        let {
           toolbar,
           plugins,
           config: pluginConfig,
           language,
         } = format.editorSettings;
+
+        // The source editing plugin is not supported in the InlineEditor.
+        // plugins = plugins.filter(item => item !== 'sourceEditing.SourceEditing');
+
         const extraPlugins = core.selectPlugins(plugins);
         const config = {
           extraPlugins,
diff --git a/js/edit_plus/fields/media.js b/js/edit_plus/fields/media.js
index ae5f0b2..9757314 100644
--- a/js/edit_plus/fields/media.js
+++ b/js/edit_plus/fields/media.js
@@ -10,9 +10,7 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
   class MediaPlugin extends fieldPluginBase.FieldPluginBase {
     constructor() {
       super();
-      this.isObserverActive = false;
       this.originalValue = null;
-      this.clonedElement = null;
     }
     supportedWidgets = [
       'media_library_widget',
diff --git a/js/edit_plus/utilities.js b/js/edit_plus/utilities.js
index 48c3f37..4354966 100644
--- a/js/edit_plus/utilities.js
+++ b/js/edit_plus/utilities.js
@@ -171,35 +171,3 @@ export const getPageElementWrapperId = (elementInfo) => {
     elementInfo.mainProperty,
   ].join('::');
 }
-
-/**
- * Edit plus update markup
- *
- * This is an AJAX method called after updating the tempstore.
- */
-jQuery.fn.EditPlusUpdateMarkup = (selector, content) => {
-  if (Drupal.EditPlus.onlyUpdateElement) {
-    // The user made changes to one form item then clicked another editable
-    // element > the next editable element was focused, the tempstore recorded the
-    // change and returned the updated page markup > let's now update only the
-    // first element that had its values recorded in the tempstore. If we were to
-    // update the whole page at this point the actively focused form element
-    // would be removed.
-    const contentElement = document.createElement('div');
-    contentElement.innerHTML = content;
-    const elementToUpdateId = Drupal.EditPlus.onlyUpdateElement.getPageElementWrapper().dataset.editPlusFieldValueWrapper;
-    const elementToUpdateSelector = '[data-edit-plus-field-value-wrapper="' + elementToUpdateId + '"]';
-    const updatedElement = contentElement.querySelector(elementToUpdateSelector);
-    const element = document.querySelector(elementToUpdateSelector);
-    element.replaceWith(updatedElement)
-    Drupal.EditPlus.onlyUpdateElement = null;
-  } else {
-    const entityWrapper = document.querySelector(selector);
-    entityWrapper.outerHTML = content;
-  }
-  Drupal.EditPlus.EnableEditMode();
-  const breakPoint = true; // @todo Remove!
-  // @todo between here and page load complete we loose all
-  // document.querySelectorAll('[data-edit-plus-original-id]')
-  // When making a change in the CTA and then clicking the eyebrow.
-}
diff --git a/src/EventSubscriber/CloneFieldAttribute.php b/src/EventSubscriber/CloneFieldAttribute.php
deleted file mode 100644
index f79775b..0000000
--- a/src/EventSubscriber/CloneFieldAttribute.php
+++ /dev/null
@@ -1,74 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\edit_plus\EventSubscriber;
-
-use Drupal\edit_plus\Event\FieldAttributes;
-use Drupal\Core\Field\FieldDefinitionInterface;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-
-/**
- * Clone field attribute.
- */
-class CloneFieldAttribute implements EventSubscriberInterface {
-
-  use AttributesTrait;
-
-  const DO_NOT_CLONE = [
-    'entity_reference_autocomplete_tags',
-    'text_textarea',
-    'text_textarea_with_summary',
-  ];
-
-  public function addFormItemAttributesAlter(FieldAttributes $event) {
-    $field_name = $event->getFieldName();
-    $form = $event->getForm();
-    $form_item = &$form[$field_name];
-    $widget = self::getWidget($event);
-
-    if (empty($form_item['#attributes']['data-edit-plus-clone']) && $widget) {
-      $field_definition = $event->getEntity()->getFieldDefinition($field_name);
-      $clone = $this->getClonedSetting($field_definition) ?? $this->getCloneDefault($widget);
-      $form_item['#attributes']['data-edit-plus-clone'] = $clone;
-      $event->setForm($form);
-    }
-  }
-
-  private function getClonedSetting(FieldDefinitionInterface $field_definition) {
-    if (method_exists($field_definition, 'getThirdPartySettings')) {
-      $third_party_settings = $field_definition->getThirdPartySettings('edit_plus');
-      if (!empty($third_party_settings['clone'])) {
-        return $third_party_settings['clone'];
-      }
-    }
-    return NULL;
-  }
-
-  /**
-   * Get Clone default setting.
-   *
-   * @param string $type
-   *   The widget type.
-   *
-   * @return string
-   *   Whether or not to clone the form item or move the original to the page
-   *   for editing.
-   */
-  private function getCloneDefault(string $type) {
-    if (!empty($type) && in_array($type, self::DO_NOT_CLONE)) {
-      return 'false';
-    }
-    return 'true';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getSubscribedEvents(): array {
-    return [
-      FieldAttributes::ALTER => ['addFormItemAttributesAlter'],
-    ];
-  }
-
-}
diff --git a/src/EventSubscriber/DefaultFieldAttributes.php b/src/EventSubscriber/DefaultFieldAttributes.php
index 034761f..2f5ac1b 100644
--- a/src/EventSubscriber/DefaultFieldAttributes.php
+++ b/src/EventSubscriber/DefaultFieldAttributes.php
@@ -41,7 +41,7 @@ class DefaultFieldAttributes implements EventSubscriberInterface {
     $display = EntityViewDisplay::collectRenderDisplay($entity, $event->getViewMode())->toArray();
     if (empty($display['hidden'][$field_name])) {
       // Hide form items of elements that will be edited inline.
-//      $form_item['#attributes']['class'][] = 'edit-plus-hidden';
+      $form_item['#attributes']['class'][] = 'edit-plus-hidden';
     } else {
       // If the field is hidden in the view mode, it can't be edited inline.
       $form_item['#attributes']['data-edit-plus-auto-submit'] = '';
diff --git a/src/EventSubscriber/MediaFieldAttributes.php b/src/EventSubscriber/MediaFieldAttributes.php
index deb882b..1b34675 100644
--- a/src/EventSubscriber/MediaFieldAttributes.php
+++ b/src/EventSubscriber/MediaFieldAttributes.php
@@ -35,7 +35,6 @@ class MediaFieldAttributes implements EventSubscriberInterface {
       $form_item['#attributes']['class'][] = 'edit-plus-hidden';
       $form_item['#attributes']['class'][] = 'edit-plus-form-item-wrapper';
       $form_item['#attributes']['data-edit-plus-handle'] = 'wrapper';
-      $form_item['#attributes']['data-edit-plus-clone'] = 'true';
       $form_item['#attributes']['data-edit-plus-form-item-wrapper-id'] = sprintf('%s::%s::%s::%s', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity), $field_name, 'value');
       $form_item['#attributes']['data-edit-plus-form-item-widget'] = self::getWidget($event);
       $form_item['widget']['#type'] = 'container';
diff --git a/src/Form/FieldConfigFormAlter.php b/src/Form/FieldConfigFormAlter.php
index 189d026..109430b 100644
--- a/src/Form/FieldConfigFormAlter.php
+++ b/src/Form/FieldConfigFormAlter.php
@@ -56,21 +56,6 @@ class FieldConfigFormAlter {
         ],
       ],
     ];
-    $form['edit_plus']['clone'] = [
-      '#type' => 'radios',
-      '#title' => t('Clone Form Item'),
-      '#default_value' => $field->getThirdPartySetting('edit_plus', 'clone') ?? 'true',
-      '#options' => [
-        'true' => $this->t('Use a clone of the form item'),
-        'false' => $this->t('Use the original form Item'),
-      ],
-      '#description' => $this->t('Select whether the inline editing for this field uses the original form item or a clone of the original form item. The cloning is based off of the handle selected above. If a clone is used, JS forwards any mouse or input events from the clone to the hidden original form element. Cloning is the prefered method since Drupal AJAX requires the form property to be set, meaning the element remains in the form, in order for many AJAX commands to work. Use the original form item for autocomplete fields as well as really simple fields.'),
-      '#states' => [
-        'invisible' => [
-          ':input[name="edit_plus[disable]"]' => ['checked' => TRUE],
-        ],
-      ],
-    ];
 
     array_unshift($form['actions']['submit']['#submit'], [$this, 'submit']);
   }
-- 
GitLab


From b4ac5bc422a488969609f3e9cedd6651fbdc151b Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Thu, 19 Sep 2024 16:59:11 -0700
Subject: [PATCH 18/33] Add contenteditable textfield plugin

---
 js/edit-plus.js                      |  5 +++
 js/edit_plus/field-plugin-manager.js |  2 ++
 js/edit_plus/fields/media.js         |  1 -
 js/edit_plus/fields/textfield.js     | 50 ++++++++++++++++++++++++++++
 4 files changed, 57 insertions(+), 1 deletion(-)
 create mode 100644 js/edit_plus/fields/textfield.js

diff --git a/js/edit-plus.js b/js/edit-plus.js
index acdabd2..7151df5 100644
--- a/js/edit-plus.js
+++ b/js/edit-plus.js
@@ -37,6 +37,11 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
    *   The click event.
    */
   Drupal.EditPlus.EditableElementClicked = (e) => {
+    if (e.target.hasAttribute('contenteditable')) {
+      // We are editing a textfield.
+      // @see textfield.js
+      return;
+    }
     // Fields are often nested. Only register one mousedown.
     e.preventDefault();
     e.stopPropagation();
diff --git a/js/edit_plus/field-plugin-manager.js b/js/edit_plus/field-plugin-manager.js
index 6e9e036..c13c337 100644
--- a/js/edit_plus/field-plugin-manager.js
+++ b/js/edit_plus/field-plugin-manager.js
@@ -2,6 +2,7 @@ import * as entityReferenceAutocomplete from './fields/entity-reference-autocomp
 import * as fieldPluginBase from './fields/field-plugin-base.js';
 import * as inlineTextarea from './fields/inline-editor.js';
 import * as defaultPlugin from './fields/default.js';
+import * as textfield from './fields/textfield.js';
 import * as mediaPlugin from './fields/media.js';
 
 /**
@@ -62,6 +63,7 @@ export default function ($ = jQuery, Drupal, once) {
    * Initialize the field plugins.
    */
   entityReferenceAutocomplete.default($, Drupal, once);
+  textfield.default($, Drupal, once);
   inlineTextarea.default($, Drupal, once);
   defaultPlugin.default($, Drupal, once);
   mediaPlugin.default($, Drupal, once);
diff --git a/js/edit_plus/fields/media.js b/js/edit_plus/fields/media.js
index 9757314..665a8bc 100644
--- a/js/edit_plus/fields/media.js
+++ b/js/edit_plus/fields/media.js
@@ -1,4 +1,3 @@
-import * as util from '../utilities.js';
 import * as entityForm from '../entity-form.js';
 import * as fieldPluginBase from './field-plugin-base.js';
 
diff --git a/js/edit_plus/fields/textfield.js b/js/edit_plus/fields/textfield.js
new file mode 100644
index 0000000..23c32be
--- /dev/null
+++ b/js/edit_plus/fields/textfield.js
@@ -0,0 +1,50 @@
+import * as defaultPlugin from './default.js';
+
+export default function ($ = jQuery, Drupal, once, dropZones) {
+
+  /**
+   * Text field plugin.
+   */
+  class TextfieldPlugin extends defaultPlugin.DefaultPlugin {
+
+    supportedWidgets = ['string_textfield'];
+
+    replacePageMarkupWithEditableElement(EditableElement) {
+      const pageElement = EditableElement.getPageElementHandle();
+      pageElement.setAttribute('contenteditable', true);
+      pageElement.classList.add('edit-plus-text-editing');
+    }
+
+    focusElement(EditableElement) {
+      this.originalValue = this.getInputValue(EditableElement);
+      const input = EditableElement.getFormItemInputs()[0];
+
+      const pageElement = EditableElement.getPageElementHandle();
+      pageElement.addEventListener('input', () => {
+        input.value = pageElement.textContent;
+      });
+      pageElement.focus();
+    }
+
+    replaceEditableElementWithMarkup(EditableElement) {
+      const pageElement = EditableElement.getPageElementHandle();
+      pageElement.removeAttribute('contenteditable');
+      pageElement.classList.remove('edit-plus-text-editing');
+    }
+
+    getFocusedSelectors() {
+      let selectors = super.getFocusedSelectors();
+      selectors.push('.edit-plus-text-editing');
+      return selectors;
+    }
+
+  }
+
+  /**
+   * Register the entity reference label field plugin.
+   */
+  window.addEventListener('EditPlusFieldManager.RegisterPlugins', e => {
+    e.detail.manager.registerPlugin(new TextfieldPlugin());
+  });
+
+}
-- 
GitLab


From 2e774b5e832c1a66c4cd524eb0ed29d358dadb59 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Fri, 20 Sep 2024 07:35:18 -0700
Subject: [PATCH 19/33] Use the right color updating text based on background
 color.

---
 css/edit-plus.css           |  9 ++------
 js/edit_plus/entity-form.js | 45 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 46 insertions(+), 8 deletions(-)

diff --git a/css/edit-plus.css b/css/edit-plus.css
index 1c9b078..b92a83d 100644
--- a/css/edit-plus.css
+++ b/css/edit-plus.css
@@ -59,19 +59,14 @@ div.edit-plus-hidden {
     bottom: 0;
     left: 0;
     right: 0;
-    background-color: rgba(0, 0, 0, 0);
-    transition: background-color .15s ease-out;
-    color: #fff;
+    transition: opacity .15s ease-out;
+    opacity: 0;
     font-size: 1rem;
     font-weight: 300;
     display: flex;
     align-items: center;
     justify-content: center;
 
-    &.background-fade-in {
-      background-color: rgba(0, 0, 0, .9);
-    }
-
     .throbber,
     .message {
       display: block;
diff --git a/js/edit_plus/entity-form.js b/js/edit_plus/entity-form.js
index da60c30..0c1f25c 100644
--- a/js/edit_plus/entity-form.js
+++ b/js/edit_plus/entity-form.js
@@ -199,9 +199,16 @@ export const updateTempstore = (EditableElement, isEmpty, form = null) => {
     pageElementWrapper.classList.add('disabled-updating');
     // Add an AJAX throbber to indicate the item is being updated.
     const throbber = Drupal.theme.ajaxProgressThrobber(Drupal.t('Updating...'));
+
     pageElementWrapper.insertAdjacentHTML('beforeend', throbber);
     setTimeout(() => {
-      document.querySelector('.disabled-updating .ajax-progress')?.classList.add('background-fade-in');
+      const progress = document.querySelector('.disabled-updating .ajax-progress');
+      if (progress) {
+        const backgroundColor = getBackgroundColor(pageElementWrapper);
+        progress.style.backgroundColor = backgroundColor;
+        progress.style.color = getTextColorForBackground(backgroundColor);
+        progress.style.opacity = '1';
+      }
     }, 50);
 
   } else {
@@ -223,6 +230,42 @@ jQuery.fn.editPlusIsDoneUpdating = () => {
   editPlusIsUpdating = false;
 };
 
+/**
+ * Get background color.
+ *
+ * @param element
+ *   The element to get the background color for.
+ *
+ * @returns {string}
+ *   The inherited background color of this element.
+ */
+export const getBackgroundColor = (element) => {
+  let currentElement = element;
+  while (currentElement) {
+    const bgColor = window.getComputedStyle(currentElement).backgroundColor;
+    if (bgColor !== 'rgba(0, 0, 0, 0)' && bgColor !== 'transparent') {
+      return bgColor;
+    }
+    currentElement = currentElement.parentElement;
+  }
+
+  return 'white';
+}
+
+export const getTextColorForBackground = (backgroundColor) => {
+  // Extract the RGB values from the string.
+  const rgb = backgroundColor.match(/\d+/g);
+  const [r, g, b] = rgb ? [parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2])] : [255, 255, 255];
+  // Calculate the luminance of the color.
+  const a = [r, g, b].map(v => {
+    v /= 255;
+    return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
+  });
+  const luminance = a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
+
+  return luminance < 0.5 ? 'white' : 'black';
+}
+
 /**
  * Edit plus update markup
  *
-- 
GitLab


From 0a8a8f15ecdd902fdcadfed6fe1f0ec63277b0e2 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Fri, 20 Sep 2024 08:35:09 -0700
Subject: [PATCH 20/33] Only immediately save block properties when the element
 isn't actively being edited.

---
 js/edit_plus/entity-form.js              | 29 ++++++++++++------------
 js/edit_plus/fields/default.js           |  7 +++++-
 js/edit_plus/fields/field-plugin-base.js |  1 -
 js/edit_plus/fields/inline-editor.js     |  5 +++-
 js/edit_plus/fields/media.js             |  5 +++-
 5 files changed, 28 insertions(+), 19 deletions(-)

diff --git a/js/edit_plus/entity-form.js b/js/edit_plus/entity-form.js
index 0c1f25c..71810f9 100644
--- a/js/edit_plus/entity-form.js
+++ b/js/edit_plus/entity-form.js
@@ -176,6 +176,16 @@ export let editPlusIsUpdating = false;
  *   but you still need to submit the form like when a sidebar form item changes.
  */
 export const updateTempstore = (EditableElement, isEmpty, form = null) => {
+  if (Drupal.EditPlus.CurrentlyEditingElement) {
+    // Say a property was changed in the sidebar, if an element is still being
+    // edited, there's no reason to save yet as there is no element on the page
+    // to update. We could just return; here and wait till the formItem is
+    // finished being updated, but the formItem might not have changes. We need
+    // to track that a save needs to occur.
+    Drupal.EditPlus.ElementNeedsSave = true;
+    return;
+  }
+
   if (!form) {
     form = EditableElement.getFormItemWrapper().closest('form');
   }
@@ -224,6 +234,10 @@ export const updateTempstore = (EditableElement, isEmpty, form = null) => {
   const updateButton = form.querySelector('.edit-plus-update-button');
   jQuery(updateButton).mousedown();
   editPlusIsUpdating = true;
+
+  if (Drupal.EditPlus.ElementNeedsSave) {
+    delete Drupal.EditPlus.ElementNeedsSave;
+  }
 }
 
 jQuery.fn.editPlusIsDoneUpdating = () => {
@@ -272,16 +286,6 @@ export const getTextColorForBackground = (backgroundColor) => {
  * This is an AJAX method called after updating the tempstore.
  */
 jQuery.fn.EditPlusUpdateMarkup = (selector, content) => {
-  if (Drupal.EditPlus.CurrentlyEditingElement) {
-    // @todo Add a "save controller" that tracks when a save needs to happen to
-    // @todo avoid unnecessary saves.
-    // Say a property was changed in the sidebar, if an element is still being
-    // edited, there's no reason to save yet as there is no element on the page
-    // to update. We could just return; here and wait till the formItem is
-    // finished being updated, but the formItem might not have changes. We need
-    // to track that a save needs to occur, collect all the changes then
-    // submit them when the pageElement needs a render.
-  }
   if (Drupal.EditPlus.onlyUpdateElement) {
     // The user made changes to one form item then clicked another editable
     // element > the next editable element was focused, the tempstore recorded the
@@ -316,11 +320,6 @@ jQuery.fn.EditPlusUpdateMarkup = (selector, content) => {
     attach: (context, settings) => {
       once('EditPlusEntityFormAutoSave', '[data-edit-plus-auto-submit]', context).forEach(formItem => {
         formItem.addEventListener('change', e => {
-          // Don't update the page as it's still being edited since it's hidden
-          // and will have to be updated again anyways.
-          if (Drupal.EditPlus.CurrentlyEditingElement) {
-            return;
-          }
           updateTempstore(null, false, e.target.closest('form'));
         });
       });
diff --git a/js/edit_plus/fields/default.js b/js/edit_plus/fields/default.js
index 7cada5c..7958d74 100644
--- a/js/edit_plus/fields/default.js
+++ b/js/edit_plus/fields/default.js
@@ -16,7 +16,12 @@ export class DefaultPlugin extends fieldPluginBase.FieldPluginBase {
   blurElement(EditableElement) {
     const inputValue = this.getInputValue(EditableElement);
     this.replaceEditableElementWithMarkup(EditableElement);
-    if (JSON.stringify(this.originalValue) !== JSON.stringify(inputValue)) {
+    if (
+      // Something flagged that this needs a save.
+      Drupal.EditPlus?.ElementNeedsSave ||
+      // The values have changed.
+      JSON.stringify(this.originalValue) !== JSON.stringify(inputValue)
+    ) {
       entityForm.updateTempstore(EditableElement, inputValue.length === 0);
     }
     this.originalValue = null;
diff --git a/js/edit_plus/fields/field-plugin-base.js b/js/edit_plus/fields/field-plugin-base.js
index 4c13c23..1a51221 100644
--- a/js/edit_plus/fields/field-plugin-base.js
+++ b/js/edit_plus/fields/field-plugin-base.js
@@ -222,7 +222,6 @@ export class FieldPluginBase {
     document.removeEventListener('scroll', this.positionEditableElementOverPageElement);
     window.removeEventListener('resize', this.positionEditableElementOverPageElement);
     Drupal.EditPlus.CurrentlyEditingElement.sizedPlaceholderHeightObserver.disconnect();
-    delete Drupal.EditPlus.CurrentlyEditingElement.sizedPlaceholderHeightObserver;
     delete Drupal.EditPlus.CurrentlyEditingElement;
 
     const pageElement = EditableElement.getPageElementHandle();
diff --git a/js/edit_plus/fields/inline-editor.js b/js/edit_plus/fields/inline-editor.js
index ebaff0c..ba95cce 100644
--- a/js/edit_plus/fields/inline-editor.js
+++ b/js/edit_plus/fields/inline-editor.js
@@ -67,7 +67,10 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
         pageElement.innerHTML = textArea.innerText = data;
       }
       this.replaceEditableElementWithMarkup(EditableElement);
-      if (data !== originalData) {
+      if (
+        Drupal.EditPlus?.ElementNeedsSave ||
+        data !== originalData
+      ) {
         entityForm.updateTempstore(EditableElement, data.length === 0);
       }
     }
diff --git a/js/edit_plus/fields/media.js b/js/edit_plus/fields/media.js
index 665a8bc..2566b45 100644
--- a/js/edit_plus/fields/media.js
+++ b/js/edit_plus/fields/media.js
@@ -22,7 +22,10 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
       const newValue = formItemWrapper.querySelector('.edit-plus-field-value img')?.src ?? null;
 
       this.replaceEditableElementWithMarkup(EditableElement);
-      if (newValue && this.originalValue !== newValue) {
+      if (
+        Drupal.EditPlus?.ElementNeedsSave ||
+        newValue && this.originalValue !== newValue
+      ) {
         entityForm.updateTempstore(EditableElement, newValue.length === 0);
       }
     }
-- 
GitLab


From 26a7c25a7d9628bfbb14671a9d4339f43a0bf8e9 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Fri, 20 Sep 2024 10:54:35 -0700
Subject: [PATCH 21/33] Pop out the editable element when there's no room

---
 README.md                                     | 10 ++++++
 css/edit-plus.css                             | 20 +++++++++++
 edit_plus.services.yml                        |  3 ++
 js/edit_plus/entity-form.js                   |  4 ++-
 js/edit_plus/fields/field-plugin-base.js      | 26 ++++++++++++--
 .../PopOutWidthFieldAttribute.php             | 36 +++++++++++++++++++
 6 files changed, 95 insertions(+), 4 deletions(-)
 create mode 100644 src/EventSubscriber/PopOutWidthFieldAttribute.php

diff --git a/README.md b/README.md
index d041e86..93a6511 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,12 @@ To relate the above editable page element to the form item that was loaded when
 ```html
 <!-- @todo 😅 -->
 ```
+To make custom block properties inline editable they need to have the wrapping markup as well. It can be added with
+```html
+<!-- @todo Review, is this even needed anymore?-->
+{% import '@edit_plus/block-property.html.twig' as block_property %}
+{{ block_property.wrapper(edit_plus, 'string', 'string', 'label', configuration.label) }}</h3>
+```
 
 
 ### Inline Editing z-index
@@ -23,3 +29,7 @@ If the inline editing z-index is undesirable for your theme override it with. Si
   z-index: 2;
 }
 ```
+
+### Pop out width
+Say you have an inline editable element, like a paragraph or a media item, and the form item widget is too big to fit inline. You can form alter a `data-pop-out-width=618` attribute onto the form item wrapper and when ever the space to edit in is smaller than the form item will show up in a pop out.
+
diff --git a/css/edit-plus.css b/css/edit-plus.css
index b92a83d..54691a0 100644
--- a/css/edit-plus.css
+++ b/css/edit-plus.css
@@ -24,6 +24,16 @@ div.edit-plus-hidden {
   width: auto;
 }
 
+.form-item-popout {
+  border: 1px solid var(--admin-toolbar-color-gray-100);
+  background-color: var(--admin-toolbar-color-white);
+  padding: 10px;
+  box-shadow:
+    0 0 72px rgba(0, 0, 0, 0.2),
+    0 0 8px rgba(0, 0, 0, 0.04),
+    0 0 40px rgba(0, 0, 0, 0.06);
+}
+
 .ck-powered-by-balloon * {
   display: none;
 }
@@ -73,3 +83,13 @@ div.edit-plus-hidden {
     }
   }
 }
+.element-ajax-throbbing {
+  /* Disable submit handlers throbber when element throbber is active. */
+  .ajax-progress {
+    display: none;
+  }
+  /* Still show the element throbber though. */
+  .disabled-updating .ajax-progress {
+    display: flex;
+  }
+}
diff --git a/edit_plus.services.yml b/edit_plus.services.yml
index db7abcb..f5870fb 100644
--- a/edit_plus.services.yml
+++ b/edit_plus.services.yml
@@ -45,3 +45,6 @@ services:
 
   edit_plus.event_subscriber.media_field_attributes:
     class: Drupal\edit_plus\EventSubscriber\MediaFieldAttributes
+
+  edit_plus.event_subscriber.pop_out_width_field_attribute:
+    class: Drupal\edit_plus\EventSubscriber\PopOutWidthFieldAttribute
diff --git a/js/edit_plus/entity-form.js b/js/edit_plus/entity-form.js
index 71810f9..425c313 100644
--- a/js/edit_plus/entity-form.js
+++ b/js/edit_plus/entity-form.js
@@ -209,7 +209,6 @@ export const updateTempstore = (EditableElement, isEmpty, form = null) => {
     pageElementWrapper.classList.add('disabled-updating');
     // Add an AJAX throbber to indicate the item is being updated.
     const throbber = Drupal.theme.ajaxProgressThrobber(Drupal.t('Updating...'));
-
     pageElementWrapper.insertAdjacentHTML('beforeend', throbber);
     setTimeout(() => {
       const progress = document.querySelector('.disabled-updating .ajax-progress');
@@ -220,6 +219,8 @@ export const updateTempstore = (EditableElement, isEmpty, form = null) => {
         progress.style.opacity = '1';
       }
     }, 50);
+    // Flag to hide the submit handler ajax throbber in the sidebar.
+    document.querySelector('body').classList.add('element-ajax-throbbing');
 
   } else {
     // EditableElement won't be available when submitting the form via EditPlusEntityFormAutoSave.
@@ -301,6 +302,7 @@ jQuery.fn.EditPlusUpdateMarkup = (selector, content) => {
     const element = document.querySelector(elementToUpdateSelector);
     element.replaceWith(updatedElement)
     Drupal.EditPlus.onlyUpdateElement = null;
+    document.querySelector('body').classList.remove('element-ajax-throbbing');
   } else {
     // Update/replace the whole thing.
     const entityWrapper = document.querySelector(selector);
diff --git a/js/edit_plus/fields/field-plugin-base.js b/js/edit_plus/fields/field-plugin-base.js
index 1a51221..c133119 100644
--- a/js/edit_plus/fields/field-plugin-base.js
+++ b/js/edit_plus/fields/field-plugin-base.js
@@ -160,12 +160,32 @@ export class FieldPluginBase {
   positionEditableElementOverPageElement() {
     const EditableElement = Drupal.EditPlus.CurrentlyEditingElement;
     const formItem = EditableElement.getFormItemHandle();
+    const popOutWidth = EditableElement.getFormItemWrapper().dataset.popOutWidth ?? 300;
     const rectangle = document.querySelector('#sized-placeholder').getBoundingClientRect();
 
     formItem.style.position = 'fixed';
-    formItem.style.left = `${rectangle.left}px`;
-    formItem.style.top = `${rectangle.top}px`;
-    formItem.style.width = `${rectangle.width}px`;
+
+    if (popOutWidth < rectangle.width) {
+      formItem.style.left = rectangle.left + 'px';
+      formItem.style.top = rectangle.top + 'px';
+      formItem.style.width = rectangle.width + 'px';
+    } else {
+      // The form item won't fit in there, make a pop out.
+      formItem.style.top = rectangle.top + 'px';
+      const width = (parseInt(popOutWidth) + 20);
+      // Center the popup over the sizedPlaceholder.
+      let left = (rectangle.left + (rectangle.width / 2)) - (popOutWidth / 2);
+      // Ensure we aren't hanging over the left edge.
+      const leftEdge = Drupal.displace.calculateOffset('left');
+      left = left > leftEdge ? left : leftEdge;
+      // Ensure we aren't hanging over the right edge.
+      const rightEdge = document.documentElement.clientWidth - Drupal.displace.calculateOffset('right');
+      left = (left + width) < rightEdge ? left : left - ((left + width) - rightEdge);
+
+      formItem.style.left = left + 'px';
+      formItem.style.width = width + 'px';
+      formItem.classList.add('form-item-popout');
+    }
   }
 
   /**
diff --git a/src/EventSubscriber/PopOutWidthFieldAttribute.php b/src/EventSubscriber/PopOutWidthFieldAttribute.php
new file mode 100644
index 0000000..53b87fc
--- /dev/null
+++ b/src/EventSubscriber/PopOutWidthFieldAttribute.php
@@ -0,0 +1,36 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\edit_plus\EventSubscriber;
+
+use Drupal\edit_plus\Event\FieldAttributes;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Pop out width field attribute.
+ */
+class PopOutWidthFieldAttribute implements EventSubscriberInterface {
+
+
+  public function addFormItemAttributesAlter(FieldAttributes $event) {
+    $form = $event->getForm();
+    $field_name = $event->getFieldName();
+    $form_item = &$form[$field_name];
+    if (empty($form_item['#attributes']['data-pop-out-width'])) {
+      $form_item['#attributes']['data-pop-out-width'] = '300';
+    }
+
+    $event->setForm($form);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents(): array {
+    return [
+      FieldAttributes::ALTER => ['addFormItemAttributesAlter'],
+    ];
+  }
+
+}
-- 
GitLab


From b3a0cf712103eca826d2dd3c8cf7e4dd38b61cf7 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Fri, 20 Sep 2024 12:03:28 -0700
Subject: [PATCH 22/33] Ensure that a plugin can be used on the editable
 element

---
 js/edit-plus.js                          |  1 +
 js/edit_plus/field-plugin-manager.js     |  2 +-
 js/edit_plus/fields/field-plugin-base.js | 84 ++++++++++++++----------
 js/edit_plus/fields/textfield.js         |  4 ++
 4 files changed, 56 insertions(+), 35 deletions(-)

diff --git a/js/edit-plus.js b/js/edit-plus.js
index 7151df5..03abeca 100644
--- a/js/edit-plus.js
+++ b/js/edit-plus.js
@@ -45,6 +45,7 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
     // Fields are often nested. Only register one mousedown.
     e.preventDefault();
     e.stopPropagation();
+
     // Deselect any currently focused fields.
     if (Drupal.EditPlus.Focused) {
       Drupal.EditPlus.FieldPluginManager.getPlugin(Drupal.EditPlus.Focused.elementInfo).blur(Drupal.EditPlus.Focused);
diff --git a/js/edit_plus/field-plugin-manager.js b/js/edit_plus/field-plugin-manager.js
index c13c337..ac681ae 100644
--- a/js/edit_plus/field-plugin-manager.js
+++ b/js/edit_plus/field-plugin-manager.js
@@ -43,7 +43,7 @@ class FieldPluginManager {
 
     Object.values(this.plugins).forEach(plugin => {
       plugin.supportedWidgets.forEach(widget => {
-        if (EditableElement.info.widget === widget) {
+        if (EditableElement.info.widget === widget && plugin.applies(EditableElement)) {
           pluginForElement = plugin;
         }
       });
diff --git a/js/edit_plus/fields/field-plugin-base.js b/js/edit_plus/fields/field-plugin-base.js
index c133119..720d40a 100644
--- a/js/edit_plus/fields/field-plugin-base.js
+++ b/js/edit_plus/fields/field-plugin-base.js
@@ -154,40 +154,6 @@ export class FieldPluginBase {
     EditableElement.getFormItemWrapper().classList.add('edit-plus-hidden');
   }
 
-  /**
-   * Position editable element over page element.
-   */
-  positionEditableElementOverPageElement() {
-    const EditableElement = Drupal.EditPlus.CurrentlyEditingElement;
-    const formItem = EditableElement.getFormItemHandle();
-    const popOutWidth = EditableElement.getFormItemWrapper().dataset.popOutWidth ?? 300;
-    const rectangle = document.querySelector('#sized-placeholder').getBoundingClientRect();
-
-    formItem.style.position = 'fixed';
-
-    if (popOutWidth < rectangle.width) {
-      formItem.style.left = rectangle.left + 'px';
-      formItem.style.top = rectangle.top + 'px';
-      formItem.style.width = rectangle.width + 'px';
-    } else {
-      // The form item won't fit in there, make a pop out.
-      formItem.style.top = rectangle.top + 'px';
-      const width = (parseInt(popOutWidth) + 20);
-      // Center the popup over the sizedPlaceholder.
-      let left = (rectangle.left + (rectangle.width / 2)) - (popOutWidth / 2);
-      // Ensure we aren't hanging over the left edge.
-      const leftEdge = Drupal.displace.calculateOffset('left');
-      left = left > leftEdge ? left : leftEdge;
-      // Ensure we aren't hanging over the right edge.
-      const rightEdge = document.documentElement.clientWidth - Drupal.displace.calculateOffset('right');
-      left = (left + width) < rightEdge ? left : left - ((left + width) - rightEdge);
-
-      formItem.style.left = left + 'px';
-      formItem.style.width = width + 'px';
-      formItem.classList.add('form-item-popout');
-    }
-  }
-
   /**
    * Replace page markup with editable element.
    *
@@ -255,6 +221,42 @@ export class FieldPluginBase {
     pageElement.classList.remove('edit-plus-hidden');
   }
 
+  /**
+   * Position editable element over page element.
+   */
+  positionEditableElementOverPageElement() {
+    const EditableElement = Drupal.EditPlus.CurrentlyEditingElement;
+    const formItem = EditableElement.getFormItemHandle();
+    const popOutWidth = EditableElement.getFormItemWrapper().dataset.popOutWidth ?? 200;
+    const rectangle = document.querySelector('#sized-placeholder').getBoundingClientRect();
+
+    formItem.style.position = 'fixed';
+
+    if (popOutWidth < rectangle.width) {
+      // The form item will fit inline.
+      formItem.style.left = rectangle.left + 'px';
+      formItem.style.top = rectangle.top + 'px';
+      formItem.style.width = rectangle.width + 'px';
+      formItem.classList.remove('form-item-popout');
+    } else {
+      // The form item won't fit in there, make a pop out.
+      formItem.style.top = rectangle.top + 'px';
+      const width = (parseInt(popOutWidth) + 20);
+      // Center the popup over the sizedPlaceholder.
+      let left = (rectangle.left + (rectangle.width / 2)) - (popOutWidth / 2);
+      // Ensure we aren't hanging over the left edge.
+      const leftEdge = Drupal.displace.calculateOffset('left');
+      left = left > leftEdge ? left : leftEdge;
+      // Ensure we aren't hanging over the right edge.
+      const rightEdge = document.documentElement.clientWidth - Drupal.displace.calculateOffset('right');
+      left = (left + width) < rightEdge ? left : left - ((left + width) - rightEdge);
+
+      formItem.style.left = left + 'px';
+      formItem.style.width = width + 'px';
+      formItem.classList.add('form-item-popout');
+    }
+  }
+
   /**
    * Get focused selectors.
    *
@@ -274,5 +276,19 @@ export class FieldPluginBase {
     ];
   }
 
+  /**
+   * Applies.
+   *
+   * When the plugin manager is selecting plugins, ensure that this plugin applies.
+   *
+   * @param EditableElement
+   *   The editable element.
+   * @returns {boolean}
+   *   Whether this plugin should be used.
+   */
+  applies(EditableElement) {
+    return true;
+  }
+
 }
 
diff --git a/js/edit_plus/fields/textfield.js b/js/edit_plus/fields/textfield.js
index 23c32be..99f20fc 100644
--- a/js/edit_plus/fields/textfield.js
+++ b/js/edit_plus/fields/textfield.js
@@ -38,6 +38,10 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
       return selectors;
     }
 
+    applies(EditableElement) {
+      return EditableElement.getHandleType() !== 'wrapper';
+    }
+
   }
 
   /**
-- 
GitLab


From 4efede9fb5a3dca8c85fd0cea1a201c6f34f45a1 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Mon, 23 Sep 2024 15:09:17 -0700
Subject: [PATCH 23/33] Pass what page element to update to the back end

---
 js/edit-plus.js                          | 14 --------------
 js/edit_plus/entity-form.js              | 23 ++++++++++++-----------
 js/edit_plus/fields/field-plugin-base.js |  3 ---
 js/edit_plus/utilities.js                |  1 -
 src/Ajax/UpdateMarkup.php                |  5 ++++-
 src/EditPlusFormTrait.php                | 14 ++++++++++----
 6 files changed, 26 insertions(+), 34 deletions(-)

diff --git a/js/edit-plus.js b/js/edit-plus.js
index 03abeca..2762fb2 100644
--- a/js/edit-plus.js
+++ b/js/edit-plus.js
@@ -16,20 +16,6 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
    */
   Drupal.EditPlus.Focused = null;
 
-  /**
-   * Only update element.
-   *
-   * Flag to only update the markup of the changed field. Usually after an
-   * element has been edited the entire entity's rendered markup is updated. If
-   * a user edit's an element and then clicks another editable element which is
-   * then replaced with the form item for editing, the form item would be
-   * overwritten/disappear when the whole entity's markup is replaced. In this
-   * instance only update the field that has changed.
-   *
-   * @type {null}
-   */
-  Drupal.EditPlus.onlyUpdateElement = null;
-
   /**
    * Editable Element clicked.
    *
diff --git a/js/edit_plus/entity-form.js b/js/edit_plus/entity-form.js
index 425c313..ae0da50 100644
--- a/js/edit_plus/entity-form.js
+++ b/js/edit_plus/entity-form.js
@@ -1,4 +1,5 @@
 import * as utilities from './utilities.js';
+import * as editableElement from './editable-element.js';
 
 /**
  * Get form.
@@ -221,12 +222,16 @@ export const updateTempstore = (EditableElement, isEmpty, form = null) => {
     }, 50);
     // Flag to hide the submit handler ajax throbber in the sidebar.
     document.querySelector('body').classList.add('element-ajax-throbbing');
-
+    // Flag to only update the rendered output of this field, not the entire
+    // entity. This allows users to continue editing the page.
+    form.querySelector('.edit-plus-only-update-element').value = EditableElement.getPageElement().dataset.editPlusId;
   } else {
     // EditableElement won't be available when submitting the form via EditPlusEntityFormAutoSave.
     const entityWrapper = document.querySelector('[data-toolbar-plus-entity-wrapper^="' + form.closest('.edit-plus-form').dataset.editPlusFormId + '"]');
     const info = utilities.parseEntityWrapperId(entityWrapper.dataset.toolbarPlusEntityWrapper);
     viewMode = info.viewMode;
+    // Flag to update the render output fo the entire entity.
+    form.querySelector('.edit-plus-only-update-element').value = null;
   }
   form.querySelector('.edit-plus-view-mode').value = viewMode;
 
@@ -286,22 +291,18 @@ export const getTextColorForBackground = (backgroundColor) => {
  *
  * This is an AJAX method called after updating the tempstore.
  */
-jQuery.fn.EditPlusUpdateMarkup = (selector, content) => {
-  if (Drupal.EditPlus.onlyUpdateElement) {
-    // The user made changes to one form item then clicked another editable
-    // element > the next editable element was focused, the tempstore recorded the
-    // change and returned the updated page markup > let's now update only the
-    // first element that had its values recorded in the tempstore. If we were to
-    // update the whole page at this point the actively focused form element
-    // would be removed.
+jQuery.fn.EditPlusUpdateMarkup = (selector, content, updatedElementId) => {
+  if (updatedElementId) {
+    // Let's update only the element that had changes so users can continue to
+    // edit other fields.
+    const EditableElement = new editableElement.EditableElement(updatedElementId);
     const contentElement = document.createElement('div');
     contentElement.innerHTML = content;
-    const elementToUpdateId = Drupal.EditPlus.onlyUpdateElement.getPageElementWrapper().dataset.editPlusFieldValueWrapper;
+    const elementToUpdateId = EditableElement.getPageElementWrapper().dataset.editPlusFieldValueWrapper;
     const elementToUpdateSelector = '[data-edit-plus-field-value-wrapper="' + elementToUpdateId + '"]';
     const updatedElement = contentElement.querySelector(elementToUpdateSelector);
     const element = document.querySelector(elementToUpdateSelector);
     element.replaceWith(updatedElement)
-    Drupal.EditPlus.onlyUpdateElement = null;
     document.querySelector('body').classList.remove('element-ajax-throbbing');
   } else {
     // Update/replace the whole thing.
diff --git a/js/edit_plus/fields/field-plugin-base.js b/js/edit_plus/fields/field-plugin-base.js
index 720d40a..87b7b1a 100644
--- a/js/edit_plus/fields/field-plugin-base.js
+++ b/js/edit_plus/fields/field-plugin-base.js
@@ -97,9 +97,6 @@ export class FieldPluginBase {
       }
     }
     if (!remainFocused) {
-      // Only update the page with the item that was just changed.
-      Drupal.EditPlus.onlyUpdateElement = Drupal.EditPlus.Focused.editableElement;
-
       plugin.blur();
       document.querySelectorAll('.edit-plus-focused').forEach(element => {
         element.classList.remove('edit-plus-focused');
diff --git a/js/edit_plus/utilities.js b/js/edit_plus/utilities.js
index 4354966..e653bb8 100644
--- a/js/edit_plus/utilities.js
+++ b/js/edit_plus/utilities.js
@@ -1,5 +1,4 @@
 import * as formatterPropertyMap from './formatter-property-map.js';
-import * as editableElement from './editable-element.js';
 
 /**
  * Parse markup ID.
diff --git a/src/Ajax/UpdateMarkup.php b/src/Ajax/UpdateMarkup.php
index 9a8bf18..aaaf962 100644
--- a/src/Ajax/UpdateMarkup.php
+++ b/src/Ajax/UpdateMarkup.php
@@ -14,10 +14,13 @@ class UpdateMarkup implements CommandInterface {
    *   A CSS selector.
    * @param array $content
    *   The content that will be updated.
+   * @param string|null $updatedElementId
+   *   The rendered element to be updated.
    */
   public function __construct(
     protected string $selector,
     protected array $content,
+    protected ?string $updatedElementId = NULL,
   ) {}
 
   public function render() {
@@ -25,7 +28,7 @@ class UpdateMarkup implements CommandInterface {
       'command' => 'invoke',
       'selector' => $this->selector,
       'method' => 'EditPlusUpdateMarkup',
-      'args' => [$this->selector, $this->getRenderedContent()],
+      'args' => [$this->selector, $this->getRenderedContent(), $this->updatedElementId],
     ];
   }
 
diff --git a/src/EditPlusFormTrait.php b/src/EditPlusFormTrait.php
index f07baaf..18db26d 100644
--- a/src/EditPlusFormTrait.php
+++ b/src/EditPlusFormTrait.php
@@ -40,6 +40,15 @@ trait EditPlusFormTrait {
       '#value' => $this->getViewMode($form, $form_state, $entity),
     ];
 
+    // Let entity-form.js updateTempstore flag to only update the markup of the
+    // changed editable element instead of the entire entity. This allows users
+    // to continue editing other fields.
+    $form['only_update_element'] = [
+      '#type' => 'hidden',
+      '#attributes' => ['class' => ['edit-plus-only-update-element']],
+      '#value' => NULL,
+    ];
+
     // @todo Shouldn't adding this button just be a FieldAttributes event?
     // @todo or is it special for some reason?
     foreach ($entity->getFieldDefinitions() as $field_name => $field_definition) {
@@ -174,8 +183,6 @@ trait EditPlusFormTrait {
       if (!empty($form['settings']['block_form']['view_mode']['#value'])) {
         // @todo This only covers inline blocks I think since it looks for the new view mode in component > content > #view_mode. Ensure that we don't need to cover other situations like entity forms.
         $form['settings']['block_form']['view_mode']['#value'] = $content['component']['content']['#view_mode'];
-        // @todo View modes are all over the place and we keep ending up with "full" from a field and then falling back to "default"
-        // @todo is this an example of where it's always right? Maybe this can be the way everything works and consolidate it in _toolbar_plus_get_view_mode
       }
 
       $input = $this->getUserInput($form_state);
@@ -183,9 +190,8 @@ trait EditPlusFormTrait {
       $form_state->setUserInput($input);
     }
 
-    // @todo On call to action you can change the view mode, then this wrapper ID is wrong 😑
     $selector = sprintf('[data-toolbar-plus-entity-wrapper="%s::%s::%s::%s"]', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity), $view_mode, $entity->bundle());
-    $response->addCommand(new UpdateMarkup($selector, $content));
+    $response->addCommand(new UpdateMarkup($selector, $content, $input['only_update_element']));
   }
 
   /**
-- 
GitLab


From 5801b64a4de921c9bf9b65a6accc18a9e692acc3 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Mon, 23 Sep 2024 15:59:20 -0700
Subject: [PATCH 24/33] Wait for ckeditor to load to gather it's value

---
 js/edit_plus/fields/default.js | 32 ++++++++++++++++++++++++++++----
 1 file changed, 28 insertions(+), 4 deletions(-)

diff --git a/js/edit_plus/fields/default.js b/js/edit_plus/fields/default.js
index 7958d74..7b3d64c 100644
--- a/js/edit_plus/fields/default.js
+++ b/js/edit_plus/fields/default.js
@@ -31,7 +31,7 @@ export class DefaultPlugin extends fieldPluginBase.FieldPluginBase {
     return EditableElement.getFormItemInputs();
   }
 
-  getInputValue(EditableElement) {
+  async getInputValue(EditableElement) {
     const inputs = this.getFormItemInputs(EditableElement);
     if (inputs[0].type === 'checkbox') {
       let checkboxes = [];
@@ -44,11 +44,35 @@ export class DefaultPlugin extends fieldPluginBase.FieldPluginBase {
       return checkboxes;
     }
     else {
+      // If there's a ckeditor here it won't be initialized on the first pass,
+      // then when the values are compared to see if there are changes, there will
+      // always be changes on the first go. Let's wait for the ckeditor to load.
+      const waitForCkeditor = (ckeditorId) =>{
+        return new Promise((resolve, reject) => {
+          const ckeditor = Drupal.CKEditor5Instances.get(ckeditorId);
+          if (ckeditor) {
+            resolve(ckeditor);
+          } else {
+            const interval = setInterval(() => {
+              const instance = Drupal.CKEditor5Instances.get(ckeditorId);
+              if (instance) {
+                clearInterval(interval);
+                resolve(instance);
+              }
+            }, 10);
+          }
+        });
+      }
+
       let values = {};
       for (let i=0; i < inputs.length; i++) {
-        values[i] = inputs[i].hasAttribute('data-ckeditor5-id') && Drupal.CKEditor5Instances.get(inputs[i].dataset.ckeditor5Id)
-          ? Drupal.CKEditor5Instances.get(inputs[i].dataset.ckeditor5Id).getData()
-          : inputs[i].value;
+        if (inputs[i].hasAttribute('data-ckeditor5-id')) {
+          const ckeditorId = inputs[i].dataset.ckeditor5Id;
+          const ckeditor = await waitForCkeditor(ckeditorId);
+          values[i] = ckeditor.getData();
+        } else {
+          values[i] = inputs[i].value;
+        }
       }
       return values;
     }
-- 
GitLab


From ed281496db9be4cc19cc5b60e6d4c8e4f9fc3298 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Tue, 24 Sep 2024 14:19:28 -0700
Subject: [PATCH 25/33] Ensure that forms initially loaded while another form
 is loading don't step on the previously loaded forms.

---
 css/edit-plus.css                        |  2 +-
 js/edit-plus.js                          | 25 +++++++++++++---------
 js/edit_plus/fields/default.js           | 27 +++++++++++++-----------
 js/edit_plus/fields/field-plugin-base.js | 26 ++++++++++-------------
 js/edit_plus/fields/textfield.js         |  4 +++-
 js/edit_plus/utilities.js                | 14 ++----------
 6 files changed, 47 insertions(+), 51 deletions(-)

diff --git a/css/edit-plus.css b/css/edit-plus.css
index 54691a0..f48f74b 100644
--- a/css/edit-plus.css
+++ b/css/edit-plus.css
@@ -20,7 +20,7 @@ div.edit-plus-hidden {
   color: #000;
 }
 
-#sized-placeholder {
+.sized-placeholder {
   width: auto;
 }
 
diff --git a/js/edit-plus.js b/js/edit-plus.js
index 2762fb2..d21f8b0 100644
--- a/js/edit-plus.js
+++ b/js/edit-plus.js
@@ -8,13 +8,13 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
   Drupal.EditPlus.EditMode = 'enabled';
 
   /**
-   * Focused Form Item.
+   * Currently Editing Element.
    *
    * Remember the focused form item. Instead of calling replaceEditableElementWithMarkup
    * onblur, lets track the focused form item so that clicking things in the
    * sidebar doesn't lose focus on the currently edited form item.
    */
-  Drupal.EditPlus.Focused = null;
+  Drupal.EditPlus.CurrentlyEditingElement = null;
 
   /**
    * Editable Element clicked.
@@ -28,17 +28,15 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
       // @see textfield.js
       return;
     }
-    // Fields are often nested. Only register one mousedown.
+
+    // Fields can be nested. Only register one mousedown.
     e.preventDefault();
     e.stopPropagation();
 
-    // Deselect any currently focused fields.
-    if (Drupal.EditPlus.Focused) {
-      Drupal.EditPlus.FieldPluginManager.getPlugin(Drupal.EditPlus.Focused.elementInfo).blur(Drupal.EditPlus.Focused);
-    }
-
     // @todo Make the default of which form is loaded initially configurable and
-    //  add a UI to switch between the entity reference forms.
+    // @todo add a UI to switch between the referenced entities forms.
+    // @todo Default to the first form, e.g. entity reference or media library
+    // @todo not the referenced entity form or the media entity form.
     let fieldValue = e.target.closest('.edit-plus-field-value');
     while (fieldValue.parentNode.closest('.edit-plus-field-value')) {
       fieldValue = fieldValue.parentNode.closest('.edit-plus-field-value');
@@ -46,7 +44,7 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
 
     const EditableElement = new editableElement.EditableElement(fieldValue.dataset.editPlusId);
 
-    // Don't edit items that are currently being updated.
+    // Prevent clicks on a form item that is currently being updated.
     if (EditableElement.getPageElementHandle().classList.contains('disabled-updating')) {
       return;
     }
@@ -54,7 +52,14 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
     entityForm.getForm(EditableElement).then((response, status) => {
       // Set the widget now that the form is loaded.
       EditableElement.setWidget();
+
+      if (Drupal.EditPlus.CurrentlyEditingElement) {
+        Drupal.EditPlus.FieldPluginManager.getPlugin(Drupal.EditPlus.CurrentlyEditingElement).blur(Drupal.EditPlus.CurrentlyEditingElement);
+      }
+
       Drupal.EditPlus.FieldPluginManager.getPlugin(EditableElement).edit(EditableElement);
+    }).catch((error) => {
+      console.error('An error occurred while loading the form:', error);
     });
   }
 
diff --git a/js/edit_plus/fields/default.js b/js/edit_plus/fields/default.js
index 7b3d64c..c30c552 100644
--- a/js/edit_plus/fields/default.js
+++ b/js/edit_plus/fields/default.js
@@ -9,22 +9,25 @@ export class DefaultPlugin extends fieldPluginBase.FieldPluginBase {
   supportedWidgets = [];
 
   focusElement(EditableElement) {
-    this.originalValue = this.getInputValue(EditableElement);
+    this.getInputValue(EditableElement).then(values => {
+      this.originalValue = values;
+    });
     this.getFormItemInputs(EditableElement)[0].focus();
   }
 
   blurElement(EditableElement) {
-    const inputValue = this.getInputValue(EditableElement);
-    this.replaceEditableElementWithMarkup(EditableElement);
-    if (
-      // Something flagged that this needs a save.
-      Drupal.EditPlus?.ElementNeedsSave ||
-      // The values have changed.
-      JSON.stringify(this.originalValue) !== JSON.stringify(inputValue)
-    ) {
-      entityForm.updateTempstore(EditableElement, inputValue.length === 0);
-    }
-    this.originalValue = null;
+    this.getInputValue(EditableElement).then(values => {
+      this.replaceEditableElementWithMarkup(EditableElement);
+      if (
+        // Something flagged that this needs a save.
+        Drupal.EditPlus?.ElementNeedsSave ||
+        // The values have changed.
+        JSON.stringify(this.originalValue) !== JSON.stringify(values)
+      ) {
+        entityForm.updateTempstore(EditableElement, values.length === 0);
+      }
+      this.originalValue = null;
+    });
   }
 
   getFormItemInputs(EditableElement) {
diff --git a/js/edit_plus/fields/field-plugin-base.js b/js/edit_plus/fields/field-plugin-base.js
index 87b7b1a..dbbbae0 100644
--- a/js/edit_plus/fields/field-plugin-base.js
+++ b/js/edit_plus/fields/field-plugin-base.js
@@ -1,3 +1,4 @@
+import * as utils from '../utilities.js';
 
 /**
  * Field plugin base.
@@ -48,12 +49,6 @@ export class FieldPluginBase {
     // currently focused so that we can check if one of its ancillary elements
     // was clicked.
     EditableElement.getFormItemWrapper().classList.add('edit-plus-focused');
-    Drupal.EditPlus.Focused = {
-      formItem: EditableElement.getFormItemHandle(),
-      elementInfo: EditableElement.info,
-      // @todo move the above to instead use Editable Element.
-      editableElement: EditableElement,
-    };
     document.addEventListener('mousedown', this.watchFocus, true);
 
     this.focusElement(EditableElement)
@@ -86,7 +81,7 @@ export class FieldPluginBase {
   watchFocus(e) {
     // Check that the clicked element is something that should cause the form
     // item to lose focus.
-    const plugin = Drupal.EditPlus.FieldPluginManager.getPlugin(Drupal.EditPlus.Focused.editableElement);
+    const plugin = Drupal.EditPlus.FieldPluginManager.getPlugin(Drupal.EditPlus.CurrentlyEditingElement);
     const getCurrentlyFocusedSelectors = plugin.getFocusedSelectors();
     let remainFocused = false;
     for (let i = 0; i < getCurrentlyFocusedSelectors.length; i++) {
@@ -110,9 +105,10 @@ export class FieldPluginBase {
    * Remove focus from the actively focused form item.
    */
   blur() {
-    const EditableElement = Drupal.EditPlus.Focused.editableElement;
+    const EditableElement = Drupal.EditPlus.CurrentlyEditingElement;
     document.removeEventListener('mousedown', this.watchFocus, true);
-    Drupal.EditPlus.Focused = null;
+    Drupal.EditPlus.CurrentlyEditingElement.sizedPlaceholderHeightObserver.disconnect();
+    Drupal.EditPlus.CurrentlyEditingElement = null;
     this.blurElement(EditableElement);
   }
 
@@ -168,7 +164,9 @@ export class FieldPluginBase {
     const sizedPlaceholder = document.createElement('div');
 
     // Add an element that the form item will hover over.
-    sizedPlaceholder.id = 'sized-placeholder';
+    const sizedPlaceholderId = utils.getSizedPlaceholderId(EditableElement)
+    sizedPlaceholder.id = sizedPlaceholderId;
+    sizedPlaceholder.classList.add('sized-placeholder');
     pageElement.parentElement.insertBefore(sizedPlaceholder, pageElement);
 
     this.positionEditableElementOverPageElement();
@@ -181,7 +179,7 @@ export class FieldPluginBase {
     // As items are added or removed from the form item via ajax, the sizedPlaceholder
     // show grow or shrink accordingly.
     Drupal.EditPlus.CurrentlyEditingElement.sizedPlaceholderHeightObserver = new ResizeObserver(entries => {
-      const sizedPlaceholder = document.querySelector('#sized-placeholder');
+      const sizedPlaceholder = document.querySelector('#' + sizedPlaceholderId);
       for (let entry of entries) {
         sizedPlaceholder.style.height = entry.contentRect.height + 'px';
       }
@@ -204,15 +202,13 @@ export class FieldPluginBase {
   replaceEditableElementWithMarkup(EditableElement) {
     document.removeEventListener('scroll', this.positionEditableElementOverPageElement);
     window.removeEventListener('resize', this.positionEditableElementOverPageElement);
-    Drupal.EditPlus.CurrentlyEditingElement.sizedPlaceholderHeightObserver.disconnect();
-    delete Drupal.EditPlus.CurrentlyEditingElement;
 
     const pageElement = EditableElement.getPageElementHandle();
     const formItem = EditableElement.getFormItemHandle();
 
     formItem.removeAttribute('style');
     formItem.classList.remove('edit-plus-editing');
-    document.querySelector('#sized-placeholder').remove();
+    document.querySelector('#' + utils.getSizedPlaceholderId(EditableElement)).remove();
 
     formItem.classList.add('edit-plus-hidden');
     pageElement.classList.remove('edit-plus-hidden');
@@ -225,7 +221,7 @@ export class FieldPluginBase {
     const EditableElement = Drupal.EditPlus.CurrentlyEditingElement;
     const formItem = EditableElement.getFormItemHandle();
     const popOutWidth = EditableElement.getFormItemWrapper().dataset.popOutWidth ?? 200;
-    const rectangle = document.querySelector('#sized-placeholder').getBoundingClientRect();
+    const rectangle = document.querySelector('#' + utils.getSizedPlaceholderId(EditableElement)).getBoundingClientRect();
 
     formItem.style.position = 'fixed';
 
diff --git a/js/edit_plus/fields/textfield.js b/js/edit_plus/fields/textfield.js
index 99f20fc..d31540c 100644
--- a/js/edit_plus/fields/textfield.js
+++ b/js/edit_plus/fields/textfield.js
@@ -16,7 +16,9 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
     }
 
     focusElement(EditableElement) {
-      this.originalValue = this.getInputValue(EditableElement);
+      this.getInputValue(EditableElement).then(values => {
+        this.originalValue = values;
+      });
       const input = EditableElement.getFormItemInputs()[0];
 
       const pageElement = EditableElement.getPageElementHandle();
diff --git a/js/edit_plus/utilities.js b/js/edit_plus/utilities.js
index e653bb8..1fabe5c 100644
--- a/js/edit_plus/utilities.js
+++ b/js/edit_plus/utilities.js
@@ -90,18 +90,8 @@ export const getFormItemId = (elementInfo) => {
   ].join('::');
 }
 
-/**
- * Get the elementInfo object
- *
- * @param formItem
- *   The form item.
- *
- * @returns {{elementId, langcode: *, fieldName: *, mainProperty: *, delta: *, entityTypeId: *, entityId: *, widget: *, viewMode: *, fieldType: *}}
- *   The elementInfo object.
- */
-export const getElementInfo = (formItem) => {
-  const markupItem = getMarkupItem(formItem);
-  return parseMarkupId(markupItem.dataset.editPlusId);
+export const getSizedPlaceholderId = (EditableElement) => {
+  return 'sized-placeholder-' + EditableElement.info.elementId.replace(/::/g, '-');
 }
 
 /**
-- 
GitLab


From 60a4972a99af0bcf8beae57c4db0f69ccb684165 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Wed, 25 Sep 2024 10:33:25 -0700
Subject: [PATCH 26/33] Toolbar+ now uses left and right sidebars

---
 js/edit_plus/entity-form.js                     | 2 +-
 js/edit_plus/fields/field-plugin-base.js        | 2 +-
 src/Controller/MultipleEntityFormController.php | 2 +-
 src/EditPlusFormTrait.php                       | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/js/edit_plus/entity-form.js b/js/edit_plus/entity-form.js
index ae0da50..9327fe8 100644
--- a/js/edit_plus/entity-form.js
+++ b/js/edit_plus/entity-form.js
@@ -101,7 +101,7 @@ const getLayoutBuilderEntityForm = (EditableElement) => {
             // @todo Is setting the selector here a hack? Consider making a renderer like Drupal\Core\Render\MainContent\AjaxRenderer.
             if (r.command === 'insert' && r.method === null && r.data && r.data.includes('edit-plus-form')) {
               r.method = 'append';
-              r.selector = '#toolbar-plus-sidebar';
+              r.selector = '#toolbar-plus-right-sidebar';
             }
           }),
         )
diff --git a/js/edit_plus/fields/field-plugin-base.js b/js/edit_plus/fields/field-plugin-base.js
index dbbbae0..c01b585 100644
--- a/js/edit_plus/fields/field-plugin-base.js
+++ b/js/edit_plus/fields/field-plugin-base.js
@@ -265,7 +265,7 @@ export class FieldPluginBase {
   getFocusedSelectors() {
     return [
       '.edit-plus-focused',
-      '#toolbar-plus-sidebar',
+      '#toolbar-plus-right-sidebar',
     ];
   }
 
diff --git a/src/Controller/MultipleEntityFormController.php b/src/Controller/MultipleEntityFormController.php
index 15966fa..32f8fea 100644
--- a/src/Controller/MultipleEntityFormController.php
+++ b/src/Controller/MultipleEntityFormController.php
@@ -84,7 +84,7 @@ final class MultipleEntityFormController extends ControllerBase {
     }
 
     $response = new AjaxResponse();
-    $response->addCommand(new AppendCommand('#toolbar-plus-sidebar', $form));
+    $response->addCommand(new AppendCommand('#toolbar-plus-right-sidebar', $form));
 
     return $response;
   }
diff --git a/src/EditPlusFormTrait.php b/src/EditPlusFormTrait.php
index 18db26d..7388121 100644
--- a/src/EditPlusFormTrait.php
+++ b/src/EditPlusFormTrait.php
@@ -279,7 +279,7 @@ trait EditPlusFormTrait {
         '#tree' => FALSE,
         '#attributes' => [
           'id' => self::getEditPlusFormId($entity),
-          'class' => ['edit-plus-form', 'toolbar-plus-sidebar'],
+          'class' => ['edit-plus-form', 'toolbar-plus-sidebar', 'right-sidebar'],
           'data-edit-plus-form-id' => sprintf('%s::%s', $entity->getEntityTypeId(), edit_plus_entity_identifier($entity)),
           'data-offset-right' => '',
         ],
-- 
GitLab


From 3580c5baa7d7600f7bfc141ef3058ce03b1bd377 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Wed, 25 Sep 2024 12:37:09 -0700
Subject: [PATCH 27/33] Ensure CKEditors are reattached

---
 js/edit_plus/entity-form.js    | 7 +++++++
 js/edit_plus/fields/default.js | 6 ++++++
 2 files changed, 13 insertions(+)

diff --git a/js/edit_plus/entity-form.js b/js/edit_plus/entity-form.js
index 9327fe8..099f0d5 100644
--- a/js/edit_plus/entity-form.js
+++ b/js/edit_plus/entity-form.js
@@ -310,6 +310,13 @@ jQuery.fn.EditPlusUpdateMarkup = (selector, content, updatedElementId) => {
     entityWrapper.outerHTML = content;
   }
   Drupal.EditPlus.EnableEditMode();
+  // Scenario: you have two forms loaded which both have CKEditors inside.
+  // when you change one then click to change the other a chain of events happens.
+  // updateTempstore clicks the save (ajax update) button > beforeSerialize
+  // detaches behaviors > all CKEditors are removed > then the CKEditor you
+  // are now editing doesn't have a CKEditor attached. Let's just call
+  // attachBehaviors here to get the editor since it is idempotent.
+  Drupal.attachBehaviors();
 }
 
 (($, Drupal, once) => {
diff --git a/js/edit_plus/fields/default.js b/js/edit_plus/fields/default.js
index c30c552..5d1694d 100644
--- a/js/edit_plus/fields/default.js
+++ b/js/edit_plus/fields/default.js
@@ -56,12 +56,18 @@ export class DefaultPlugin extends fieldPluginBase.FieldPluginBase {
           if (ckeditor) {
             resolve(ckeditor);
           } else {
+            let count = 0;
+            const limit = 10;
             const interval = setInterval(() => {
               const instance = Drupal.CKEditor5Instances.get(ckeditorId);
               if (instance) {
                 clearInterval(interval);
                 resolve(instance);
               }
+              if (count >= limit) {
+                clearInterval(interval);
+                reject(new Error(`Invalid value for ${ckeditorId}`));
+              }
             }, 10);
           }
         });
-- 
GitLab


From abf3b5553090e499567219d0989563ca52dba511 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Wed, 25 Sep 2024 15:08:47 -0700
Subject: [PATCH 28/33] Tweak setting CurrentlyEditingElement

---
 js/edit_plus/fields/field-plugin-base.js | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/js/edit_plus/fields/field-plugin-base.js b/js/edit_plus/fields/field-plugin-base.js
index c01b585..0c7a59a 100644
--- a/js/edit_plus/fields/field-plugin-base.js
+++ b/js/edit_plus/fields/field-plugin-base.js
@@ -28,6 +28,7 @@ export class FieldPluginBase {
    *   The element being edited.
    */
   edit(EditableElement) {
+    Drupal.EditPlus.CurrentlyEditingElement = EditableElement;
     this.replacePageMarkupWithEditableElement(EditableElement);
     this.focus(EditableElement);
     this.revealAncillary(EditableElement);
@@ -107,7 +108,9 @@ export class FieldPluginBase {
   blur() {
     const EditableElement = Drupal.EditPlus.CurrentlyEditingElement;
     document.removeEventListener('mousedown', this.watchFocus, true);
-    Drupal.EditPlus.CurrentlyEditingElement.sizedPlaceholderHeightObserver.disconnect();
+    if (Drupal.EditPlus.CurrentlyEditingElement.sizedPlaceholderHeightObserver) {
+      Drupal.EditPlus.CurrentlyEditingElement.sizedPlaceholderHeightObserver.disconnect();
+    }
     Drupal.EditPlus.CurrentlyEditingElement = null;
     this.blurElement(EditableElement);
   }
@@ -157,8 +160,6 @@ export class FieldPluginBase {
    *   The element being edited.
    */
   replacePageMarkupWithEditableElement(EditableElement) {
-    Drupal.EditPlus.CurrentlyEditingElement = EditableElement;
-
     const pageElement = EditableElement.getPageElementHandle();
     const formItem = EditableElement.getFormItemHandle();
     const sizedPlaceholder = document.createElement('div');
-- 
GitLab


From 05b531614d64cf447cca34c2414bdc4ce603432a Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Thu, 26 Sep 2024 11:22:46 -0700
Subject: [PATCH 29/33] Fix inline editing not focusing on safari

---
 css/ckeditor.css                     | 39 +++++++++++++++++++++-------
 js/edit_plus/fields/inline-editor.js | 10 +++++--
 2 files changed, 37 insertions(+), 12 deletions(-)

diff --git a/css/ckeditor.css b/css/ckeditor.css
index 104bd78..4136915 100644
--- a/css/ckeditor.css
+++ b/css/ckeditor.css
@@ -1,15 +1,15 @@
-:not(form) .edit-plus-form-item {
-  margin: 0;
-}
+/*:not(form) .edit-plus-form-item {*/
+/*  margin: 0;*/
+/*}*/
 
-:not(form) .edit-plus-inline-edit.ck.ck-blurred {
-  padding-left: 0;
-}
+/*:not(form) .edit-plus-inline-edit.ck.ck-blurred {*/
+/*  padding-left: 0;*/
+/*}*/
 
-:not(form) .edit-plus-inline-edit.ck.ck-blurred > :first-child,
-:not(form) .edit-plus-inline-edit.ck.ck-blurred > :last-child {
-  margin-top: inherit;
-}
+/*:not(form) .edit-plus-inline-edit.ck.ck-blurred > :first-child,*/
+/*:not(form) .edit-plus-inline-edit.ck.ck-blurred > :last-child {*/
+/*  margin-top: inherit;*/
+/*}*/
 
 .edit-plus-form-item .ck-content {
   min-height: auto;
@@ -18,3 +18,22 @@
 .ck-body-wrapper .ck.ck-balloon-panel {
   z-index: 2;
 }
+
+/* The source plugin isn't supported in InlineEditor */
+.ck.ck-button.ck-source-editing-button {
+  display: none;
+}
+/* Still allow it in ClassicEditor's though. */
+.edit-plus-form-item .ck.ck-button.ck-source-editing-button {
+  display: flex;
+}
+
+/**
+ * Fix safari not focusing because of admin-reset-style.css
+   :where([data-drupal-admin-styles] :not(svg *)) {
+     all: revert;
+   }
+ */
+[data-drupal-admin-styles] .edit-plus-inline-edit * {
+  -webkit-user-modify: read-write;
+}
diff --git a/js/edit_plus/fields/inline-editor.js b/js/edit_plus/fields/inline-editor.js
index ba95cce..0ca5670 100644
--- a/js/edit_plus/fields/inline-editor.js
+++ b/js/edit_plus/fields/inline-editor.js
@@ -37,7 +37,10 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
         const editor = Drupal.EditPlus.Ckeditor5Instances.get(ckeditor5Id);
         if (editor) {
           setTimeout(() => {
-            editor.focus();
+            // Normally you'd call editor.focus() here, but it's not playing
+            // nice with safari. Let's manually fire the event.
+            editor.ui.focusTracker.isFocused = true;
+            editor.editing.view.document.fire('focus');
           }, 0);
         } else {
           // The editor hasn't been built yet because the form was just loaded.
@@ -270,7 +273,10 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
             // the editor as soon as it's created.
             if (id === Drupal.EditPlus.FocusInlineEditor) {
               Drupal.EditPlus.FocusInlineEditor = null;
-              editor.focus();
+              // Normally you'd call editor.focus() here, but it's not playing
+              // nice with safari. Let's manually fire the event.
+              editor.ui.focusTracker.isFocused = true;
+              editor.editing.view.document.fire('focus');
 
               // Remember the editors original state.
               const EditableElement = editableElement.EditableElement.createFromFormItem(formItem);
-- 
GitLab


From 0584b9f867d7f2092bda5a03f6c319376317727e Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Thu, 26 Sep 2024 14:30:09 -0700
Subject: [PATCH 30/33] Suspend updates while editing flag and set the plugin
 on the EditableElement

---
 css/ckeditor.css                         |  2 +-
 js/edit-plus.js                          |  2 +-
 js/edit_plus/editable-element.js         | 10 +++++++++-
 js/edit_plus/entity-form.js              |  8 ++------
 js/edit_plus/fields/field-plugin-base.js | 15 +++++++++++++++
 js/edit_plus/fields/textfield.js         |  2 ++
 6 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/css/ckeditor.css b/css/ckeditor.css
index 4136915..9cf89c4 100644
--- a/css/ckeditor.css
+++ b/css/ckeditor.css
@@ -34,6 +34,6 @@
      all: revert;
    }
  */
-[data-drupal-admin-styles] .edit-plus-inline-edit * {
+[data-drupal-admin-styles] .ck * {
   -webkit-user-modify: read-write;
 }
diff --git a/js/edit-plus.js b/js/edit-plus.js
index d21f8b0..7fcbd0f 100644
--- a/js/edit-plus.js
+++ b/js/edit-plus.js
@@ -57,7 +57,7 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
         Drupal.EditPlus.FieldPluginManager.getPlugin(Drupal.EditPlus.CurrentlyEditingElement).blur(Drupal.EditPlus.CurrentlyEditingElement);
       }
 
-      Drupal.EditPlus.FieldPluginManager.getPlugin(EditableElement).edit(EditableElement);
+      EditableElement.plugin.edit(EditableElement);
     }).catch((error) => {
       console.error('An error occurred while loading the form:', error);
     });
diff --git a/js/edit_plus/editable-element.js b/js/edit_plus/editable-element.js
index 66bda6d..b36a514 100644
--- a/js/edit_plus/editable-element.js
+++ b/js/edit_plus/editable-element.js
@@ -8,8 +8,15 @@ import * as util from './utilities.js';
  */
 export class EditableElement {
 
+  /**
+   * The field plugin for this EditableElement.
+   *
+   * @type FieldPluginBase
+   */
+  plugin = null;
+
   constructor(id) {
-    this.info = util.parseMarkupId(id)
+    this.info = util.parseMarkupId(id);
   }
 
   /**
@@ -24,6 +31,7 @@ export class EditableElement {
 
   setWidget() {
     this.info.widget = this.getFormItemWrapper().dataset.editPlusFormItemWidget;
+    this.plugin = Drupal.EditPlus.FieldPluginManager.getPlugin(this);
   }
 
   /**
diff --git a/js/edit_plus/entity-form.js b/js/edit_plus/entity-form.js
index 099f0d5..0af241c 100644
--- a/js/edit_plus/entity-form.js
+++ b/js/edit_plus/entity-form.js
@@ -177,12 +177,8 @@ export let editPlusIsUpdating = false;
  *   but you still need to submit the form like when a sidebar form item changes.
  */
 export const updateTempstore = (EditableElement, isEmpty, form = null) => {
-  if (Drupal.EditPlus.CurrentlyEditingElement) {
-    // Say a property was changed in the sidebar, if an element is still being
-    // edited, there's no reason to save yet as there is no element on the page
-    // to update. We could just return; here and wait till the formItem is
-    // finished being updated, but the formItem might not have changes. We need
-    // to track that a save needs to occur.
+  if (Drupal.EditPlus.CurrentlyEditingElement && Drupal.EditPlus.CurrentlyEditingElement.plugin.suspendUpdatesWhileEditing) {
+    // Flag that this element needs a save later.
     Drupal.EditPlus.ElementNeedsSave = true;
     return;
   }
diff --git a/js/edit_plus/fields/field-plugin-base.js b/js/edit_plus/fields/field-plugin-base.js
index 0c7a59a..fd70eb4 100644
--- a/js/edit_plus/fields/field-plugin-base.js
+++ b/js/edit_plus/fields/field-plugin-base.js
@@ -21,6 +21,21 @@ export class FieldPluginBase {
    */
   supportedWidgets = [];
 
+  /**
+   * Suspend updates while editing.
+   *
+   *  Say a property was changed in the sidebar, if an element is still being
+   *  edited, there's no reason to save yet as there is no element on the page
+   *  to update. We could just return; here and wait till the formItem is
+   *  finished being updated, but the formItem might not have changes. We need
+   *  to track that a save needs to occur. Not all field types want this behavior
+   *  e.g. textfields.
+   *  @see updateTempstore
+   *
+   * @type {boolean}
+   */
+  suspendUpdatesWhileEditing = true;
+
   /**
    * Edit.
    *
diff --git a/js/edit_plus/fields/textfield.js b/js/edit_plus/fields/textfield.js
index d31540c..754c39c 100644
--- a/js/edit_plus/fields/textfield.js
+++ b/js/edit_plus/fields/textfield.js
@@ -9,6 +9,8 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
 
     supportedWidgets = ['string_textfield'];
 
+    suspendUpdatesWhileEditing = false;
+
     replacePageMarkupWithEditableElement(EditableElement) {
       const pageElement = EditableElement.getPageElementHandle();
       pageElement.setAttribute('contenteditable', true);
-- 
GitLab


From 0557c3544d0fa5eb79ceafc92b090e571cd561bb Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Thu, 26 Sep 2024 14:44:57 -0700
Subject: [PATCH 31/33] Use whatever the original font color was while editing

---
 js/edit_plus/fields/inline-editor.js | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/js/edit_plus/fields/inline-editor.js b/js/edit_plus/fields/inline-editor.js
index 0ca5670..64cc537 100644
--- a/js/edit_plus/fields/inline-editor.js
+++ b/js/edit_plus/fields/inline-editor.js
@@ -32,7 +32,10 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
 
     focusElement(EditableElement) {
       const formItem = EditableElement.getFormItem();
-      const ckeditor5Id = formItem.querySelector('.edit-plus-inline-edit').dataset.ckeditor5Id;
+      const sourceElement = formItem.querySelector('.edit-plus-inline-edit');
+      // Use whatever the original font color was while editing.
+      sourceElement.style.color = window.getComputedStyle(EditableElement.getPageElement()).color;
+      const ckeditor5Id = sourceElement.dataset.ckeditor5Id;
       if (ckeditor5Id) {
         const editor = Drupal.EditPlus.Ckeditor5Instances.get(ckeditor5Id);
         if (editor) {
-- 
GitLab


From 4391a744f47f6997d0f384abb5dbb72a86481971 Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Thu, 26 Sep 2024 16:40:22 -0700
Subject: [PATCH 32/33] Ensure that changes are collected before updating the
 tempstore.

---
 css/ckeditor.css                         | 23 +++--------
 css/edit-plus.css                        |  5 ---
 js/edit-plus.js                          |  2 +-
 js/edit_plus/editable-element.js         |  2 +-
 js/edit_plus/entity-form.js              | 22 +++++++----
 js/edit_plus/fields/default.js           | 10 ++---
 js/edit_plus/fields/field-plugin-base.js | 49 ++++++++++++------------
 js/edit_plus/fields/inline-editor.js     | 17 ++++----
 js/edit_plus/fields/media.js             |  6 +--
 js/edit_plus/fields/textfield.js         |  8 ++--
 10 files changed, 64 insertions(+), 80 deletions(-)

diff --git a/css/ckeditor.css b/css/ckeditor.css
index 9cf89c4..6e2531c 100644
--- a/css/ckeditor.css
+++ b/css/ckeditor.css
@@ -1,16 +1,3 @@
-/*:not(form) .edit-plus-form-item {*/
-/*  margin: 0;*/
-/*}*/
-
-/*:not(form) .edit-plus-inline-edit.ck.ck-blurred {*/
-/*  padding-left: 0;*/
-/*}*/
-
-/*:not(form) .edit-plus-inline-edit.ck.ck-blurred > :first-child,*/
-/*:not(form) .edit-plus-inline-edit.ck.ck-blurred > :last-child {*/
-/*  margin-top: inherit;*/
-/*}*/
-
 .edit-plus-form-item .ck-content {
   min-height: auto;
 }
@@ -28,11 +15,11 @@
   display: flex;
 }
 
-/**
- * Fix safari not focusing because of admin-reset-style.css
-   :where([data-drupal-admin-styles] :not(svg *)) {
-     all: revert;
-   }
+/*
+Fix safari not focusing because of admin-reset-style.css
+  :where([data-drupal-admin-styles] :not(svg *)) {
+    all: revert;
+  }
  */
 [data-drupal-admin-styles] .ck * {
   -webkit-user-modify: read-write;
diff --git a/css/edit-plus.css b/css/edit-plus.css
index f48f74b..a5541d3 100644
--- a/css/edit-plus.css
+++ b/css/edit-plus.css
@@ -53,11 +53,6 @@ div.edit-plus-hidden {
   to { background-color: rgba(121, 189, 143, 0)}
 }
 
-/* @todo Remove when we stop using block decorators. */
-.block .button.js-hide {
-  display: none;
-}
-
 /* AJAX throbber */
 .disabled-updating {
   position: relative;
diff --git a/js/edit-plus.js b/js/edit-plus.js
index 7fcbd0f..c6e559a 100644
--- a/js/edit-plus.js
+++ b/js/edit-plus.js
@@ -54,7 +54,7 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
       EditableElement.setWidget();
 
       if (Drupal.EditPlus.CurrentlyEditingElement) {
-        Drupal.EditPlus.FieldPluginManager.getPlugin(Drupal.EditPlus.CurrentlyEditingElement).blur(Drupal.EditPlus.CurrentlyEditingElement);
+        Drupal.EditPlus.CurrentlyEditingElement.plugin.blur(Drupal.EditPlus.CurrentlyEditingElement);
       }
 
       EditableElement.plugin.edit(EditableElement);
diff --git a/js/edit_plus/editable-element.js b/js/edit_plus/editable-element.js
index b36a514..c49d1cc 100644
--- a/js/edit_plus/editable-element.js
+++ b/js/edit_plus/editable-element.js
@@ -11,7 +11,7 @@ export class EditableElement {
   /**
    * The field plugin for this EditableElement.
    *
-   * @type FieldPluginBase
+   * @type {FieldPluginBase}
    */
   plugin = null;
 
diff --git a/js/edit_plus/entity-form.js b/js/edit_plus/entity-form.js
index 0af241c..6cdcf29 100644
--- a/js/edit_plus/entity-form.js
+++ b/js/edit_plus/entity-form.js
@@ -176,12 +176,22 @@ export let editPlusIsUpdating = false;
  *   Pass the form element directly when an EditableElement isn't available,
  *   but you still need to submit the form like when a sidebar form item changes.
  */
-export const updateTempstore = (EditableElement, isEmpty, form = null) => {
-  if (Drupal.EditPlus.CurrentlyEditingElement && Drupal.EditPlus.CurrentlyEditingElement.plugin.suspendUpdatesWhileEditing) {
-    // Flag that this element needs a save later.
-    Drupal.EditPlus.ElementNeedsSave = true;
+export const updateTempstore = async (EditableElement, isEmpty, form = null) => {
+  if (updateTempstore.alreadyUpdating) {
     return;
   }
+  if (!EditableElement && Drupal.EditPlus.CurrentlyEditingElement) {
+    // We are saving something other than an EditableElement while an
+    // EditableElement is focused. Probably something in the sidebar. Let's
+    // blur the CurrentlyEditingElement to get any changes from it.
+    // Flag that we are already updating as blur can call updateTempstore again.
+    updateTempstore.alreadyUpdating = true;
+    try {
+      await Drupal.EditPlus.CurrentlyEditingElement.plugin.blur();
+    } finally {
+      updateTempstore.alreadyUpdating = false;
+    }
+  }
 
   if (!form) {
     form = EditableElement.getFormItemWrapper().closest('form');
@@ -236,10 +246,6 @@ export const updateTempstore = (EditableElement, isEmpty, form = null) => {
   const updateButton = form.querySelector('.edit-plus-update-button');
   jQuery(updateButton).mousedown();
   editPlusIsUpdating = true;
-
-  if (Drupal.EditPlus.ElementNeedsSave) {
-    delete Drupal.EditPlus.ElementNeedsSave;
-  }
 }
 
 jQuery.fn.editPlusIsDoneUpdating = () => {
diff --git a/js/edit_plus/fields/default.js b/js/edit_plus/fields/default.js
index 5d1694d..d44091f 100644
--- a/js/edit_plus/fields/default.js
+++ b/js/edit_plus/fields/default.js
@@ -16,14 +16,10 @@ export class DefaultPlugin extends fieldPluginBase.FieldPluginBase {
   }
 
   blurElement(EditableElement) {
-    this.getInputValue(EditableElement).then(values => {
+    return this.getInputValue(EditableElement).then(values => {
       this.replaceEditableElementWithMarkup(EditableElement);
-      if (
-        // Something flagged that this needs a save.
-        Drupal.EditPlus?.ElementNeedsSave ||
-        // The values have changed.
-        JSON.stringify(this.originalValue) !== JSON.stringify(values)
-      ) {
+      // The values have changed.
+      if (JSON.stringify(this.originalValue) !== JSON.stringify(values)) {
         entityForm.updateTempstore(EditableElement, values.length === 0);
       }
       this.originalValue = null;
diff --git a/js/edit_plus/fields/field-plugin-base.js b/js/edit_plus/fields/field-plugin-base.js
index fd70eb4..bdc4bb3 100644
--- a/js/edit_plus/fields/field-plugin-base.js
+++ b/js/edit_plus/fields/field-plugin-base.js
@@ -21,21 +21,6 @@ export class FieldPluginBase {
    */
   supportedWidgets = [];
 
-  /**
-   * Suspend updates while editing.
-   *
-   *  Say a property was changed in the sidebar, if an element is still being
-   *  edited, there's no reason to save yet as there is no element on the page
-   *  to update. We could just return; here and wait till the formItem is
-   *  finished being updated, but the formItem might not have changes. We need
-   *  to track that a save needs to occur. Not all field types want this behavior
-   *  e.g. textfields.
-   *  @see updateTempstore
-   *
-   * @type {boolean}
-   */
-  suspendUpdatesWhileEditing = true;
-
   /**
    * Edit.
    *
@@ -63,7 +48,7 @@ export class FieldPluginBase {
     // on the form item doesn't necessarily mean we are done with it. e.g.
     // changing a text format in the sidebar. Let's keep track of what is
     // currently focused so that we can check if one of its ancillary elements
-    // was clicked.
+    // was clicked and remain focused.
     EditableElement.getFormItemWrapper().classList.add('edit-plus-focused');
     document.addEventListener('mousedown', this.watchFocus, true);
 
@@ -97,7 +82,7 @@ export class FieldPluginBase {
   watchFocus(e) {
     // Check that the clicked element is something that should cause the form
     // item to lose focus.
-    const plugin = Drupal.EditPlus.FieldPluginManager.getPlugin(Drupal.EditPlus.CurrentlyEditingElement);
+    const plugin = Drupal.EditPlus.CurrentlyEditingElement.plugin;
     const getCurrentlyFocusedSelectors = plugin.getFocusedSelectors();
     let remainFocused = false;
     for (let i = 0; i < getCurrentlyFocusedSelectors.length; i++) {
@@ -120,14 +105,14 @@ export class FieldPluginBase {
    *
    * Remove focus from the actively focused form item.
    */
-  blur() {
+  async blur() {
     const EditableElement = Drupal.EditPlus.CurrentlyEditingElement;
     document.removeEventListener('mousedown', this.watchFocus, true);
     if (Drupal.EditPlus.CurrentlyEditingElement.sizedPlaceholderHeightObserver) {
       Drupal.EditPlus.CurrentlyEditingElement.sizedPlaceholderHeightObserver.disconnect();
     }
     Drupal.EditPlus.CurrentlyEditingElement = null;
-    this.blurElement(EditableElement);
+    return this.blurElement(EditableElement);
   }
 
   /**
@@ -140,8 +125,14 @@ export class FieldPluginBase {
    *
    * @param EditableElement
    *   The element being edited.
+   *
+   * @returns {Promise<void>}
+   *   Getting the form inputs needs to be async since we may need to wait on
+   *   a CKEditor to be attached before getting changes.
    */
-  blurElement(EditableElement) {}
+  blurElement(EditableElement) {
+    return Promise.resolve();
+  }
 
   /**
    * Reveal ancillary.
@@ -179,7 +170,7 @@ export class FieldPluginBase {
     const formItem = EditableElement.getFormItemHandle();
     const sizedPlaceholder = document.createElement('div');
 
-    // Add an element that the form item will hover over.
+    // Add a placeholder element that the form item will hover over.
     const sizedPlaceholderId = utils.getSizedPlaceholderId(EditableElement)
     sizedPlaceholder.id = sizedPlaceholderId;
     sizedPlaceholder.classList.add('sized-placeholder');
@@ -196,8 +187,10 @@ export class FieldPluginBase {
     // show grow or shrink accordingly.
     Drupal.EditPlus.CurrentlyEditingElement.sizedPlaceholderHeightObserver = new ResizeObserver(entries => {
       const sizedPlaceholder = document.querySelector('#' + sizedPlaceholderId);
-      for (let entry of entries) {
-        sizedPlaceholder.style.height = entry.contentRect.height + 'px';
+      if (sizedPlaceholder) {
+        for (let entry of entries) {
+          sizedPlaceholder.style.height = entry.contentRect.height + 'px';
+        }
       }
     });
     Drupal.EditPlus.CurrentlyEditingElement.sizedPlaceholderHeightObserver.observe(formItem);
@@ -224,7 +217,10 @@ export class FieldPluginBase {
 
     formItem.removeAttribute('style');
     formItem.classList.remove('edit-plus-editing');
-    document.querySelector('#' + utils.getSizedPlaceholderId(EditableElement)).remove();
+    const sizedPlaceholder = document.querySelector('#' + utils.getSizedPlaceholderId(EditableElement));
+    if (sizedPlaceholder) {
+      sizedPlaceholder.remove();
+    }
 
     formItem.classList.add('edit-plus-hidden');
     pageElement.classList.remove('edit-plus-hidden');
@@ -232,6 +228,11 @@ export class FieldPluginBase {
 
   /**
    * Position editable element over page element.
+   *
+   * The editable element is position: fixed over the placeholder. The
+   * placeholder not only pushes content further down the page as if the
+   * editable element is in place there, but it also gives us the dimensions that
+   * the editable element should have.
    */
   positionEditableElementOverPageElement() {
     const EditableElement = Drupal.EditPlus.CurrentlyEditingElement;
diff --git a/js/edit_plus/fields/inline-editor.js b/js/edit_plus/fields/inline-editor.js
index 64cc537..f8b6568 100644
--- a/js/edit_plus/fields/inline-editor.js
+++ b/js/edit_plus/fields/inline-editor.js
@@ -73,12 +73,10 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
         pageElement.innerHTML = textArea.innerText = data;
       }
       this.replaceEditableElementWithMarkup(EditableElement);
-      if (
-        Drupal.EditPlus?.ElementNeedsSave ||
-        data !== originalData
-      ) {
+      if (data !== originalData) {
         entityForm.updateTempstore(EditableElement, data.length === 0);
       }
+      return Promise.resolve();
     }
 
     revealAncillary(EditableElement) {
@@ -197,7 +195,7 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
     attachEditorWithNewFormat: (EditableElement, markupElement, format) => {
       once.remove('EditPlusAttachEditor', markupElement);
       Drupal.behaviors.EditPlusInlineEditors.showInputElement(markupElement, format);
-      Drupal.EditPlus.FieldPluginManager.getPlugin(EditableElement).focus(EditableElement);
+      EditableElement.plugin.focus(EditableElement);
     },
 
     /**
@@ -249,7 +247,9 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
           language,
         } = format.editorSettings;
 
-        // The source editing plugin is not supported in the InlineEditor.
+        // @todo The source editing plugin is not supported in the InlineEditor.
+        // It is currently hidden with CSS, but let's do something that accounts for
+        // block separators so you don't get 2 of them together ||.
         // plugins = plugins.filter(item => item !== 'sourceEditing.SourceEditing');
 
         const extraPlugins = core.selectPlugins(plugins);
@@ -281,9 +281,10 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
               editor.ui.focusTracker.isFocused = true;
               editor.editing.view.document.fire('focus');
 
-              // Remember the editors original state.
+              // Remember the editors original state so we can detect if it has
+              // changed and trigger a tempstore update.
               const EditableElement = editableElement.EditableElement.createFromFormItem(formItem);
-              const plugin = Drupal.EditPlus.FieldPluginManager.getPlugin(EditableElement);
+              const plugin = EditableElement.plugin;
               plugin.originalData.set(EditableElement.info.elementId, plugin.getInputValue(formItem));
 
             }
diff --git a/js/edit_plus/fields/media.js b/js/edit_plus/fields/media.js
index 2566b45..ad76d3e 100644
--- a/js/edit_plus/fields/media.js
+++ b/js/edit_plus/fields/media.js
@@ -22,12 +22,10 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
       const newValue = formItemWrapper.querySelector('.edit-plus-field-value img')?.src ?? null;
 
       this.replaceEditableElementWithMarkup(EditableElement);
-      if (
-        Drupal.EditPlus?.ElementNeedsSave ||
-        newValue && this.originalValue !== newValue
-      ) {
+      if (newValue && this.originalValue !== newValue) {
         entityForm.updateTempstore(EditableElement, newValue.length === 0);
       }
+      return Promise.resolve();
     }
 
     getFocusedSelectors() {
diff --git a/js/edit_plus/fields/textfield.js b/js/edit_plus/fields/textfield.js
index 754c39c..f820026 100644
--- a/js/edit_plus/fields/textfield.js
+++ b/js/edit_plus/fields/textfield.js
@@ -9,8 +9,6 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
 
     supportedWidgets = ['string_textfield'];
 
-    suspendUpdatesWhileEditing = false;
-
     replacePageMarkupWithEditableElement(EditableElement) {
       const pageElement = EditableElement.getPageElementHandle();
       pageElement.setAttribute('contenteditable', true);
@@ -32,8 +30,10 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
 
     replaceEditableElementWithMarkup(EditableElement) {
       const pageElement = EditableElement.getPageElementHandle();
-      pageElement.removeAttribute('contenteditable');
-      pageElement.classList.remove('edit-plus-text-editing');
+      if (pageElement) {
+        pageElement.removeAttribute('contenteditable');
+        pageElement.classList.remove('edit-plus-text-editing');
+      }
     }
 
     getFocusedSelectors() {
-- 
GitLab


From d586f6f230f64dd2239a2223f2ad535d36a62a4e Mon Sep 17 00:00:00 2001
From: Tim Bozeman <tim@timbozeman.com>
Date: Thu, 26 Sep 2024 17:20:30 -0700
Subject: [PATCH 33/33] Clean up

---
 README.md                                     |  15 +-
 css/bottom-bar.css                            |   8 +-
 css/ckeditor.css                              |   2 +-
 css/edit-plus.css                             |  14 +-
 edit_plus.module                              |   3 -
 edit_plus.services.yml                        |   6 +-
 js/edit-plus.js                               |  16 +-
 js/edit_plus/editable-element.js              | 194 ++++++++++++------
 js/edit_plus/effects.js                       |  20 +-
 js/edit_plus/entity-form.js                   |  44 ++--
 js/edit_plus/field-plugin-manager.js          |  12 +-
 js/edit_plus/formatter-property-map.js        |   2 +
 js/edit_plus/{fields => plugins}/default.js   |  16 +-
 .../entity-reference-autocomplete.js          |   0
 .../{fields => plugins}/field-plugin-base.js  |  55 +++--
 .../{fields => plugins}/inline-editor.js      |  28 +--
 js/edit_plus/{fields => plugins}/media.js     |   2 +-
 js/edit_plus/{fields => plugins}/textfield.js |   4 +-
 js/edit_plus/utilities.js                     | 162 ---------------
 .../edit_plus_lb/edit_plus_lb.services.yml    |   7 +-
 .../edit_plus_lb/src/Form/UpdateBlockForm.php |  11 +-
 .../MultipleEntityFormController.php          |  13 +-
 src/EditPlusFormTrait.php                     |  23 +--
 src/EventSubscriber/AttributesTrait.php       |  14 +-
 .../DefaultFieldAttributes.php                |  10 +-
 src/EventSubscriber/HandleFieldAttribute.php  |   1 -
 .../PopOutWidthFieldAttribute.php             |   3 +-
 src/Form/InlineEntityFormAlter.php            |   2 -
 src/Form/ViewsFormMediaLibraryWidgetAlter.php |   7 +-
 src/Ui.php                                    |  51 -----
 30 files changed, 314 insertions(+), 431 deletions(-)
 rename js/edit_plus/{fields => plugins}/default.js (86%)
 rename js/edit_plus/{fields => plugins}/entity-reference-autocomplete.js (100%)
 rename js/edit_plus/{fields => plugins}/field-plugin-base.js (82%)
 rename js/edit_plus/{fields => plugins}/inline-editor.js (93%)
 rename js/edit_plus/{fields => plugins}/media.js (95%)
 rename js/edit_plus/{fields => plugins}/textfield.js (93%)
 delete mode 100644 js/edit_plus/utilities.js
 delete mode 100644 src/Ui.php

diff --git a/README.md b/README.md
index 93a6511..85e9b2b 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,10 @@
 # Edit +
-Edit+ works by loading the relevant entity form into the sidebar as a "context" sidebar. The form items are hidden. When an editable element is clicked on the page the form item is swapped into place for inline editing.
+
+# Troubleshooting
+Edit+ works by loading the relevant entity form into the sidebar as a "context" sidebar. The form items are hidden initially, but when an editable element is clicked on the page the form item is swapped into place for inline editing.
 
 ### Associating the Form Item with the Page element
-To make the UI aware of an editable page element it needs to end up with the following markup or provide its own Edit+ field widget JS plugin. There can of course be more to this markup, but these are whats required for inline editing. Please see `edit_plus_preprocess_field()` for details.
+This should happen automatically for most field items. If there are custom things going on it needs to satisfy a few things. To make the UI aware of an editable page element it needs to end up with the following markup or provide its own Edit+ field widget JS plugin. There can of course be more to this markup, but these are whats required for inline editing. Please see `edit_plus_preprocess_field()` for details.
 ```html
 <div data-edit-plus-field-value-wrapper="block_content::bc74a654-2ba6-447a-a8a0-497776cb2ba4::field_links_links::value">
   <div class="edit-plus-field-value" data-edit-plus-id="block_content::bc74a654-2ba6-447a-a8a0-497776cb2ba4::field_links_links::0::en::default::link::link::value" data-edit-plus-page-element-id="block_content::bc74a654-2ba6-447a-a8a0-497776cb2ba4::field_links_links::0::value">
@@ -12,16 +14,9 @@ To make the UI aware of an editable page element it needs to end up with the fol
 ```
 To relate the above editable page element to the form item that was loaded when it was clicked we need the following markup on the form item.
 ```html
-<!-- @todo 😅 -->
-```
-To make custom block properties inline editable they need to have the wrapping markup as well. It can be added with
-```html
-<!-- @todo Review, is this even needed anymore?-->
-{% import '@edit_plus/block-property.html.twig' as block_property %}
-{{ block_property.wrapper(edit_plus, 'string', 'string', 'label', configuration.label) }}</h3>
+<!-- @todo add an example 😅 -->
 ```
 
-
 ### Inline Editing z-index
 If the inline editing z-index is undesirable for your theme override it with. Since the inline editor is visually moved out of the sidebar, it inherits whatever the sidebar z-index is.
 ```html
diff --git a/css/bottom-bar.css b/css/bottom-bar.css
index 563b93a..dfbe272 100644
--- a/css/bottom-bar.css
+++ b/css/bottom-bar.css
@@ -1,9 +1,9 @@
 #edit-plus-bottom-bar {
   background-color: black;
   align-items: center;
+  padding: 0.5em 1em;
   position: fixed;
   flex-wrap: wrap;
-  padding: 0.5em 1em;
   display: flex;
   z-index: 500;
   bottom: 0;
@@ -14,13 +14,13 @@
 
 #edit-plus-bottom-bar .button {
   background-color: black;
+  text-decoration: none;
+  margin: 0 1em 0 0;
   font-size: 18px;
+  cursor: pointer;
   color: white;
   border: none;
   padding: 1em;
-  text-decoration: none;
-  margin: 0 1em 0 0;
-  cursor: pointer;
 }
 
 #edit-plus-bottom-bar .button:hover {
diff --git a/css/ckeditor.css b/css/ckeditor.css
index 6e2531c..df2b433 100644
--- a/css/ckeditor.css
+++ b/css/ckeditor.css
@@ -16,7 +16,7 @@
 }
 
 /*
-Fix safari not focusing because of admin-reset-style.css
+Fix Inline CKEditor in Safari not focusing because of admin-reset-style.css
   :where([data-drupal-admin-styles] :not(svg *)) {
     all: revert;
   }
diff --git a/css/edit-plus.css b/css/edit-plus.css
index a5541d3..0817ad4 100644
--- a/css/edit-plus.css
+++ b/css/edit-plus.css
@@ -11,7 +11,7 @@ div.edit-plus-hidden {
 
 #edit_plus {
   position: fixed;
-  z-index: 999999999999;
+  z-index: 10;
   margin-left: 50%;
   cursor: pointer;
   padding: 1em;
@@ -53,24 +53,24 @@ div.edit-plus-hidden {
   to { background-color: rgba(121, 189, 143, 0)}
 }
 
-/* AJAX throbber */
+/* Inline Element update AJAX throbber */
 .disabled-updating {
   position: relative;
 
   .ajax-progress {
-    user-select: none;
     position: absolute;
-    top: 0;
+    user-select: none;
+    display: flex;
     bottom: 0;
+    top: 0;
     left: 0;
     right: 0;
-    transition: opacity .15s ease-out;
     opacity: 0;
     font-size: 1rem;
     font-weight: 300;
-    display: flex;
     align-items: center;
     justify-content: center;
+    transition: opacity .15s ease-out;
 
     .throbber,
     .message {
@@ -79,7 +79,7 @@ div.edit-plus-hidden {
   }
 }
 .element-ajax-throbbing {
-  /* Disable submit handlers throbber when element throbber is active. */
+  /* Disable the forms submit handlers throbber when element throbber is active. */
   .ajax-progress {
     display: none;
   }
diff --git a/edit_plus.module b/edit_plus.module
index bbf6b86..8bc19d0 100644
--- a/edit_plus.module
+++ b/edit_plus.module
@@ -106,9 +106,6 @@ function edit_plus_preprocess_block(&$variables) {
   $entity = $variables['elements']['content']['#block_content'];
   $id = edit_plus_entity_identifier($entity);
   $view_mode = _toolbar_plus_get_view_mode($entity, $variables['content']['#view_mode']);
-  // There are two ways to make a block property editable. We special case the
-  // block label here with the prefix and suffix. Modules can also call the
-  // @todo twig function to wrap it.
   $variables['edit_plus'] = [
     'id' => $id,
     'type' => $entity->getEntityTypeId(),
diff --git a/edit_plus.services.yml b/edit_plus.services.yml
index f5870fb..257fa92 100644
--- a/edit_plus.services.yml
+++ b/edit_plus.services.yml
@@ -5,7 +5,7 @@ services:
 
   edit_plus.form_alter.inline_entity_form:
     class: Drupal\edit_plus\Form\InlineEntityFormAlter
-    arguments: ['@entity_display.repository', '@edit_plus.tempstore_repository', '@field_sample_value.generator', '@entity_type.manager', '@event_dispatcher', '@module_handler', '@renderer', '@request_stack', '@edit_plus.ui' ]
+    arguments: ['@entity_display.repository', '@edit_plus.tempstore_repository', '@field_sample_value.generator', '@entity_type.manager', '@event_dispatcher', '@module_handler', '@renderer', '@request_stack']
 
   edit_plus.form_alter.entity_edit:
     class: Drupal\edit_plus\Form\EntityEditFormAlter
@@ -31,11 +31,9 @@ services:
     class: Drupal\edit_plus\InlineEditorElement
     arguments: [ '@plugin.manager.editor' ]
 
-  edit_plus.ui:
-    class: Drupal\edit_plus\Ui
-
   edit_plus.event_subscriber.default_field_attributes:
     class: Drupal\edit_plus\EventSubscriber\DefaultFieldAttributes
+    arguments: [ '@event_dispatcher' ]
 
   edit_plus.event_subscriber.handle_field_attribute:
     class: Drupal\edit_plus\EventSubscriber\HandleFieldAttribute
diff --git a/js/edit-plus.js b/js/edit-plus.js
index c6e559a..027cb26 100644
--- a/js/edit-plus.js
+++ b/js/edit-plus.js
@@ -1,3 +1,4 @@
+import * as effects from './edit_plus/effects.js'; // Don't remove!
 import * as entityForm from './edit_plus/entity-form.js';
 import * as editableElement from './edit_plus/editable-element.js';
 import * as pluginManager from './edit_plus/field-plugin-manager.js';
@@ -10,7 +11,7 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
   /**
    * Currently Editing Element.
    *
-   * Remember the focused form item. Instead of calling replaceEditableElementWithMarkup
+   * Remember the focused form item. Instead of calling replaceFormItemWithPageElement
    * onblur, lets track the focused form item so that clicking things in the
    * sidebar doesn't lose focus on the currently edited form item.
    */
@@ -58,8 +59,9 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
       }
 
       EditableElement.plugin.edit(EditableElement);
+
     }).catch((error) => {
-      console.error('An error occurred while loading the form:', error);
+      console.error('An error occurred while trying to edit an element:', error);
     });
   }
 
@@ -95,6 +97,13 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
     });
   }
 
+  /**
+   * Not updating.
+   *
+   * Wait till edit+ is done updating.
+   *
+   * @returns {Promise<unknown>}
+   */
   Drupal.EditPlus.notUpdating = () => {
     return new Promise(resolve => {
       const intervalId = setInterval(() => {
@@ -126,7 +135,7 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
     }
   };
 
-
+  // Register field plugins.
   pluginManager.default($, Drupal, once);
 
   /**
@@ -136,6 +145,7 @@ import * as pluginManager from './edit_plus/field-plugin-manager.js';
     e.preventDefault();
     e.stopPropagation();
   };
+
   Drupal.EditPlus.DisableInteractiveElements = () => {
     $('.toolbar-plus-entity-wrapper')
       .find('a')
diff --git a/js/edit_plus/editable-element.js b/js/edit_plus/editable-element.js
index c49d1cc..38fa5d7 100644
--- a/js/edit_plus/editable-element.js
+++ b/js/edit_plus/editable-element.js
@@ -1,22 +1,69 @@
-import * as util from './utilities.js';
+import * as formatterPropertyMap from './formatter-property-map.js';
 
 /**
  * Editable Element.
  *
- * This class is a state object that represents the binding of the currently
+ * This class is a state object that represents the relationship of the currently
  * edited page element to the form element.
  */
 export class EditableElement {
 
   /**
-   * The field plugin for this EditableElement.
+   * Info
+   *
+   * All the details about this editable element.
+   *
+   * @type {{elementId, langcode: *, fieldName: *, mainProperty: *, delta: *, entityTypeId: *, entityId: *, widget: *, viewMode: *, fieldType: *, widget: *}}
+   */
+  info = null;
+
+  /**
+   * The inline editing field plugin for this EditableElement.
+   * @see field-plugin-manager.js
    *
    * @type {FieldPluginBase}
    */
   plugin = null;
 
   constructor(id) {
-    this.info = util.parseMarkupId(id);
+    this.info = this.parseMarkupId(id);
+  }
+
+  /**
+   * Create from form item.
+   *
+   * @param element
+   *   An element within a form item wrapper.
+   *
+   * @returns {EditableElement}
+   *   A new EditableElement instance from a form item or any element from
+   *   within a form item wrapper.
+   */
+  static createFromFormItem(element) {
+    // Find the page element
+    let pageElement;
+    const wrapper = element.closest('[data-edit-plus-page-element-edit-plus-id]')
+    if (wrapper) {
+      pageElement =  document.querySelector('[data-edit-plus-id="' + wrapper.dataset.editPlusPageElementEditPlusId + '"]');
+    } else {
+      // Inline Editor
+      let formItem = element.closest('.edit-plus-form-item');
+      pageElement =  document.querySelector('[data-edit-plus-page-element-id="' + formItem.dataset.editPlusFormItemId + '"]');
+    }
+
+    const editableElement = new EditableElement(pageElement.dataset.editPlusId);
+    editableElement.setWidget();
+    return editableElement;
+  }
+
+  /**
+   * Set widget.
+   *
+   * Once the form is loaded the widget needs to be set on the EditableElement.
+   */
+  setWidget() {
+    this.info.widget = this.getFormItemWrapper().dataset.editPlusFormItemWidget;
+    this.plugin = Drupal.EditPlus.FieldPluginManager.getPlugin(this);
   }
 
   /**
@@ -26,12 +73,38 @@ export class EditableElement {
    * The form for the EditableElement.
    */
   getForm() {
-    return document.querySelector('[data-edit-plus-form-id="' + util.getFormId(this.info) + '"]');
+    const id = [
+      this.info.entityTypeId,
+      this.info.entityId,
+    ].join('::');
+    return document.querySelector('[data-edit-plus-form-id="' + id + '"]');
   }
 
-  setWidget() {
-    this.info.widget = this.getFormItemWrapper().dataset.editPlusFormItemWidget;
-    this.plugin = Drupal.EditPlus.FieldPluginManager.getPlugin(this);
+  /**
+   * Get handle type.
+   *
+   * @returns {string}
+   *   Returns a string of either form_item or wrapper.
+   *
+   *   Users can config whether a field swaps the form item or the entire form
+   *   wrapper into the page for editing.
+   */
+  getHandleType() {
+    return this.getFormItemWrapper()?.dataset.editPlusHandle ?? 'form_item';
+  }
+
+  /**
+   * Handle is wrapper.
+   *
+   * @see getFormItemHandle
+   *
+   * @returns {boolean}
+   *   Returns true if the handle is wrapper. false if the handle is form_item.
+   */
+  handleIsWrapper() {
+    const wrapper = this.getFormItemWrapper();
+    const elementToUseAsHandle = wrapper.dataset.editPlusHandle ?? 'form_item';
+    return elementToUseAsHandle === 'wrapper';
   }
 
   /**
@@ -45,7 +118,13 @@ export class EditableElement {
   }
 
   getPageElementWrapper() {
-    return document.querySelector('[data-edit-plus-field-value-wrapper="' + util.getPageElementWrapperId(this.info) + '"]');
+    const id = [
+      this.info.entityTypeId,
+      this.info.entityId,
+      this.info.fieldName,
+      this.info.mainProperty,
+    ].join('::');
+    return document.querySelector('[data-edit-plus-field-value-wrapper="' + id + '"]');
   }
 
   getPageElementHandle() {
@@ -55,6 +134,22 @@ export class EditableElement {
     return document.querySelector('[data-edit-plus-id="' + this.info.elementId + '"]');
   }
 
+  /**
+   * Get Form Item ID.
+   *
+   * @returns {string}
+   *   The form item ID.
+   */
+  getFormItemId() {
+    return [
+      this.info.entityTypeId,
+      this.info.entityId,
+      this.info.fieldName,
+      this.info.delta,
+      formatterPropertyMap.getProperty(this.info),
+    ].join('::');
+  }
+
   /**
    * Get form item.
    *
@@ -62,7 +157,7 @@ export class EditableElement {
    * The form item for the EditableElement.
    */
   getFormItem() {
-    return document.querySelector('[data-edit-plus-form-item-id="' + util.getFormItemId(this.info) + '"]');
+    return document.querySelector('[data-edit-plus-form-item-id="' + this.getFormItemId() + '"]');
   }
 
   /**
@@ -72,7 +167,13 @@ export class EditableElement {
    *   The form item wrapper for the EditableElement.
    */
   getFormItemWrapper() {
-    return document.querySelector('[data-edit-plus-form-item-wrapper-id="' + util.getFormItemWrapperId(this.info) + '"]');
+    const id = [
+      this.info.entityTypeId,
+      this.info.entityId,
+      this.info.fieldName,
+      formatterPropertyMap.getProperty(this.info),
+    ].join('::');
+    return document.querySelector('[data-edit-plus-form-item-wrapper-id="' + id + '"]');
   }
 
   /**
@@ -86,20 +187,7 @@ export class EditableElement {
     if (this.getHandleType() === 'wrapper') {
       return this.getFormItemWrapper();
     }
-    return document.querySelector('[data-edit-plus-form-item-id="' + util.getFormItemId(this.info) + '"]').closest('.edit-plus-form-item');
-  }
-
-  /**
-   * Get handle type.
-   *
-   * @returns {string}
-   *   Returns a string of either form_item or wrapper.
-   *
-   *   Users can config whether a field swaps the form item or the entire form
-   *   wrapper into the page for editing.
-   */
-  getHandleType() {
-    return this.getFormItemWrapper()?.dataset.editPlusHandle ?? 'form_item';
+    return document.querySelector('[data-edit-plus-form-item-id="' + this.getFormItemId() + '"]').closest('.edit-plus-form-item');
   }
 
   /**
@@ -112,48 +200,34 @@ export class EditableElement {
     return this.getFormItemHandle().querySelectorAll('[data-edit-plus-input]');
   }
 
-  /**
-   * Get form place marker.
-   *
-   * @returns {Element}
-   *   The place marker element for the EditableElement.
-   *
-   *   When a form item is moved from the form to the page for editing a
-   *   placeholder is created to mark where the form item originated from.
-   */
-  getFormPlaceMarker() {
-    return document.querySelector('[data-form-item-placeholder="' + util.getFormItemWrapperId(this.info) + '"]');
-  }
 
-  /**
-   * Handle is wrapper.
-   *
-   * @see getFormItemHandle
-   *
-   * @returns {boolean}
-   *   Returns true if the handle is wrapper. false if the handle is form_item.
-   */
-  handleIsWrapper() {
-    const wrapper = this.getFormItemWrapper();
-    const elementToUseAsHandle = wrapper.dataset.editPlusHandle ?? 'form_item';
-    return elementToUseAsHandle === 'wrapper';
+  getSizedPlaceholderId() {
+    return 'sized-placeholder-' + this.info.elementId.replace(/::/g, '-');
   }
 
   /**
-   * Create from form item.
+   * Parse markup ID.
    *
-   * @param element
-   *   An element within a form item wrapper.
+   * @param id
+   *   The Entity Plus ID on the rendered field value.
    *
-   * @returns {EditableElement}
-   *   A new EditableElement instance from a form item or any element from
-   *   within a form item wrapper.
+   * @returns {{elementId, langcode: *, fieldName: *, mainProperty: *, delta: *, entityTypeId: *, entityId: *, widget: *, viewMode: *, fieldType: *}}
+   *   The elementInfo object.
    */
-  static createFromFormItem(element) {
-    const pageElement = util.getPageElement(element);
-    const editableElement = new EditableElement(pageElement.dataset.editPlusId);
-    editableElement.setWidget();
-    return editableElement;
+  parseMarkupId(id) {
+    const parts = id.split('::');
+    return {
+      entityTypeId: parts[0],
+      entityId: parts[1],
+      fieldName: parts[2],
+      delta: parts[3],
+      langcode: parts[4],
+      viewMode: parts[5],
+      fieldType: parts[6],
+      fieldFormatter: parts[7],
+      mainProperty: parts[8],
+      elementId: id,
+    };
   }
 
 }
diff --git a/js/edit_plus/effects.js b/js/edit_plus/effects.js
index 0be0c91..8466cd0 100644
--- a/js/edit_plus/effects.js
+++ b/js/edit_plus/effects.js
@@ -1,16 +1,20 @@
-import * as util from './utilities.js';
+import * as editableElement from './editable-element.js';
 
 (($, Drupal, once) => {
   Drupal.behaviors.EditPlusFieldAddedToPage = {
     attach: (context, settings) => {
       once('EditPlusFieldAddedToPage', '.edit-plus-field-added-to-page', context).forEach(formItem => {
-        let markupItem = util.getMarkupItem(formItem);
-        if (markupItem) {
-          // Use the field wrapper if it's available.
-          markupItem = markupItem.closest('.field') ?? markupItem;
-          // Animate adding the field to the page.
-          markupItem.classList.add('edit-plus-field-added-to-page-effect');
-        }
+
+        // @todo Review this. If creating the EditableElement here proves unreliable
+        // we need to implement something like the getMarkupItem that was removed from
+        // utilities.js
+
+        const EditableElement = editableElement.EditableElement.createFromFormItem(formItem);
+        const pageElement = EditableElement.getPageElementHandle();
+        // Use the field wrapper if it's available.
+        const element = pageElement.closest('.field') ?? pageElement;
+        // Animate adding the field to the page.
+        element.classList.add('edit-plus-field-added-to-page-effect');
       });
     }
   };
diff --git a/js/edit_plus/entity-form.js b/js/edit_plus/entity-form.js
index 6cdcf29..1e33d4b 100644
--- a/js/edit_plus/entity-form.js
+++ b/js/edit_plus/entity-form.js
@@ -1,4 +1,3 @@
-import * as utilities from './utilities.js';
 import * as editableElement from './editable-element.js';
 
 /**
@@ -33,7 +32,7 @@ export const getForm = (EditableElement) => {
   const layoutBuilderBlock = pageElement.closest('.block-layout-builder');
   if (layoutBuilderBlock) {
     // Use the regular entity form for field blocks.
-    // @todo Maybe add a field-block class that we don't need to search for...
+    // @todo Maybe add a different field-block class that we don't need to search for...
     let isFieldBlock = false;
     for (let i=0; i < layoutBuilderBlock.classList.length; i++) {
       isFieldBlock = layoutBuilderBlock.classList[i].includes('field-block');
@@ -107,7 +106,7 @@ const getLayoutBuilderEntityForm = (EditableElement) => {
         )
           .then(() => {
             Drupal.Ajax.prototype.success.call(ajax, response, status).then(() => {
-              resolve({status: 'new_form'});
+              resolve({ status: 'new_form' });
             });
           });
       }
@@ -160,6 +159,8 @@ const getEntityForm = (EditableElement) => {
 /**
  * Flag that the page is currently being updated.
  *
+ * @see Drupal.EditPlus.notUpdating
+ *
  * @type {boolean}
  */
 export let editPlusIsUpdating = false;
@@ -203,16 +204,16 @@ export const updateTempstore = async (EditableElement, isEmpty, form = null) =>
   }
 
   // Update the hidden view mode input in order to persist the view mode across
-  // multiple form submissions as it could change during one of them.
+  // multiple form submissions as it could be changing in this update.
   let viewMode;
   if (EditableElement) {
     // I think we can standardize on getting the view mode from the form > entity
-    // wrapper relationship, but we might as well get it from EditableElement
-    // when it's available as it's a tiny bit faster.
+    // wrapper relationship detailed in the else, but we might as well get it
+    // from EditableElement when it's available as it's a tiny bit faster.
     viewMode = EditableElement.info.viewMode;
 
-    const pageElementWrapper = EditableElement.getPageElementWrapper();
     // Disable editing the item while it's being updated.
+    const pageElementWrapper = EditableElement.getPageElementWrapper();
     pageElementWrapper.classList.add('disabled-updating');
     // Add an AJAX throbber to indicate the item is being updated.
     const throbber = Drupal.theme.ajaxProgressThrobber(Drupal.t('Updating...'));
@@ -229,16 +230,18 @@ export const updateTempstore = async (EditableElement, isEmpty, form = null) =>
     // Flag to hide the submit handler ajax throbber in the sidebar.
     document.querySelector('body').classList.add('element-ajax-throbbing');
     // Flag to only update the rendered output of this field, not the entire
-    // entity. This allows users to continue editing the page.
+    // entity. This allows users to continue editing other items on the page.
     form.querySelector('.edit-plus-only-update-element').value = EditableElement.getPageElement().dataset.editPlusId;
   } else {
     // EditableElement won't be available when submitting the form via EditPlusEntityFormAutoSave.
     const entityWrapper = document.querySelector('[data-toolbar-plus-entity-wrapper^="' + form.closest('.edit-plus-form').dataset.editPlusFormId + '"]');
-    const info = utilities.parseEntityWrapperId(entityWrapper.dataset.toolbarPlusEntityWrapper);
-    viewMode = info.viewMode;
-    // Flag to update the render output fo the entire entity.
+    const parts = entityWrapper.dataset.toolbarPlusEntityWrapper.split('::');
+    viewMode = parts[2];
+    // Flag to update the render output of the entire entity.
     form.querySelector('.edit-plus-only-update-element').value = null;
   }
+  // Update the hidden view mode input in order to persist the view mode across
+  // multiple form submissions as it could be changing in this update.
   form.querySelector('.edit-plus-view-mode').value = viewMode;
 
 
@@ -248,6 +251,11 @@ export const updateTempstore = async (EditableElement, isEmpty, form = null) =>
   editPlusIsUpdating = true;
 }
 
+/**
+ * Edit+ is done updating.
+ *
+ * AJAX callback that flags that the update is complete.
+ */
 jQuery.fn.editPlusIsDoneUpdating = () => {
   editPlusIsUpdating = false;
 };
@@ -274,6 +282,18 @@ export const getBackgroundColor = (element) => {
   return 'white';
 }
 
+/**
+ * Get text color for background.
+ *
+ * We don't want to have black text on a black background or other similarly
+ * un-contrasty situations.
+ *
+ * @param backgroundColor
+ *   The background color the text will appear on.
+ *
+ * @returns {string}
+ *   white or black, which would be a better choice given the background color.
+ */
 export const getTextColorForBackground = (backgroundColor) => {
   // Extract the RGB values from the string.
   const rgb = backgroundColor.match(/\d+/g);
@@ -317,7 +337,7 @@ jQuery.fn.EditPlusUpdateMarkup = (selector, content, updatedElementId) => {
   // updateTempstore clicks the save (ajax update) button > beforeSerialize
   // detaches behaviors > all CKEditors are removed > then the CKEditor you
   // are now editing doesn't have a CKEditor attached. Let's just call
-  // attachBehaviors here to get the editor since it is idempotent.
+  // attachBehaviors again here to get the editor since it is idempotent.
   Drupal.attachBehaviors();
 }
 
diff --git a/js/edit_plus/field-plugin-manager.js b/js/edit_plus/field-plugin-manager.js
index ac681ae..e7d6bdf 100644
--- a/js/edit_plus/field-plugin-manager.js
+++ b/js/edit_plus/field-plugin-manager.js
@@ -1,9 +1,9 @@
-import * as entityReferenceAutocomplete from './fields/entity-reference-autocomplete.js';
-import * as fieldPluginBase from './fields/field-plugin-base.js';
-import * as inlineTextarea from './fields/inline-editor.js';
-import * as defaultPlugin from './fields/default.js';
-import * as textfield from './fields/textfield.js';
-import * as mediaPlugin from './fields/media.js';
+import * as entityReferenceAutocomplete from './plugins/entity-reference-autocomplete.js';
+import * as fieldPluginBase from './plugins/field-plugin-base.js';
+import * as inlineTextarea from './plugins/inline-editor.js';
+import * as defaultPlugin from './plugins/default.js';
+import * as textfield from './plugins/textfield.js';
+import * as mediaPlugin from './plugins/media.js';
 
 /**
  * Field plugin manager.
diff --git a/js/edit_plus/formatter-property-map.js b/js/edit_plus/formatter-property-map.js
index 257378e..cb5fe1a 100644
--- a/js/edit_plus/formatter-property-map.js
+++ b/js/edit_plus/formatter-property-map.js
@@ -5,6 +5,8 @@ export const formatterPropertyMapping = {
 /**
  * Get property.
  *
+ * @todo Describe the problem space around this!
+ *
  * @param elementInfo
  * @returns {*|string}
  */
diff --git a/js/edit_plus/fields/default.js b/js/edit_plus/plugins/default.js
similarity index 86%
rename from js/edit_plus/fields/default.js
rename to js/edit_plus/plugins/default.js
index d44091f..879c133 100644
--- a/js/edit_plus/fields/default.js
+++ b/js/edit_plus/plugins/default.js
@@ -6,10 +6,10 @@ import * as fieldPluginBase from './field-plugin-base.js';
  */
 export class DefaultPlugin extends fieldPluginBase.FieldPluginBase {
 
-  supportedWidgets = [];
-
   focusElement(EditableElement) {
     this.getInputValue(EditableElement).then(values => {
+      // Remember the original values so we can tell if there's changes before
+      // updating when the form item looses focus.
       this.originalValue = values;
     });
     this.getFormItemInputs(EditableElement)[0].focus();
@@ -17,7 +17,7 @@ export class DefaultPlugin extends fieldPluginBase.FieldPluginBase {
 
   blurElement(EditableElement) {
     return this.getInputValue(EditableElement).then(values => {
-      this.replaceEditableElementWithMarkup(EditableElement);
+      this.replaceFormItemWithPageElement(EditableElement);
       // The values have changed.
       if (JSON.stringify(this.originalValue) !== JSON.stringify(values)) {
         entityForm.updateTempstore(EditableElement, values.length === 0);
@@ -30,6 +30,16 @@ export class DefaultPlugin extends fieldPluginBase.FieldPluginBase {
     return EditableElement.getFormItemInputs();
   }
 
+  /**
+   * Get input value(s).
+   *
+   * @param EditableElement
+   *   The editable element.
+   *
+   * @returns {Promise<{}|*[]>}
+   *   A promise because we may need to wait on a CKEditor to be attached before
+   *   getting input changes.
+   */
   async getInputValue(EditableElement) {
     const inputs = this.getFormItemInputs(EditableElement);
     if (inputs[0].type === 'checkbox') {
diff --git a/js/edit_plus/fields/entity-reference-autocomplete.js b/js/edit_plus/plugins/entity-reference-autocomplete.js
similarity index 100%
rename from js/edit_plus/fields/entity-reference-autocomplete.js
rename to js/edit_plus/plugins/entity-reference-autocomplete.js
diff --git a/js/edit_plus/fields/field-plugin-base.js b/js/edit_plus/plugins/field-plugin-base.js
similarity index 82%
rename from js/edit_plus/fields/field-plugin-base.js
rename to js/edit_plus/plugins/field-plugin-base.js
index bdc4bb3..4f80696 100644
--- a/js/edit_plus/fields/field-plugin-base.js
+++ b/js/edit_plus/plugins/field-plugin-base.js
@@ -1,5 +1,3 @@
-import * as utils from '../utilities.js';
-
 /**
  * Field plugin base.
  *
@@ -17,7 +15,7 @@ export class FieldPluginBase {
    * Supported widgets.
    *
    * @type {[]}
-   *   An array of field formatter ID's this plugin supports.
+   *   An array of widget ID's this plugin supports.
    */
   supportedWidgets = [];
 
@@ -29,7 +27,7 @@ export class FieldPluginBase {
    */
   edit(EditableElement) {
     Drupal.EditPlus.CurrentlyEditingElement = EditableElement;
-    this.replacePageMarkupWithEditableElement(EditableElement);
+    this.replacePageElementWithFormItem(EditableElement);
     this.focus(EditableElement);
     this.revealAncillary(EditableElement);
   }
@@ -103,7 +101,7 @@ export class FieldPluginBase {
   /**
    * Blur.
    *
-   * Remove focus from the actively focused form item.
+   * Remove focus from the focused form item.
    */
   async blur() {
     const EditableElement = Drupal.EditPlus.CurrentlyEditingElement;
@@ -120,8 +118,9 @@ export class FieldPluginBase {
    *
    * This should be overridden by field plugins to provide field specific
    * instructions on how to remove focus from the element. Since detecting if
-   * the field has changes after editing it's recommended for field plugins to
-   * call this.replaceEditableElementWithMarkup(EditableElement) when appropriate.
+   * the field has changes occurs at this point, after editing, it's recommended
+   * for field plugins to call this.replaceFormItemWithPageElement(EditableElement)
+   * when appropriate.
    *
    * @param EditableElement
    *   The element being edited.
@@ -157,30 +156,28 @@ export class FieldPluginBase {
   }
 
   /**
-   * Replace page markup with editable element.
+   * Replace page element with form item.
    *
-   * Visually moves a form item from the form in the sidebar over the editable
-   * element that was clicked in the main page area.
+   * Visually moves the hidden form item from the form in the sidebar over the
+   * editable element that was clicked in the main page area.
    *
    * @param EditableElement
    *   The element being edited.
    */
-  replacePageMarkupWithEditableElement(EditableElement) {
+  replacePageElementWithFormItem(EditableElement) {
     const pageElement = EditableElement.getPageElementHandle();
     const formItem = EditableElement.getFormItemHandle();
-    const sizedPlaceholder = document.createElement('div');
 
     // Add a placeholder element that the form item will hover over.
-    const sizedPlaceholderId = utils.getSizedPlaceholderId(EditableElement)
+    const sizedPlaceholderId = EditableElement.getSizedPlaceholderId()
+    const sizedPlaceholder = document.createElement('div');
     sizedPlaceholder.id = sizedPlaceholderId;
     sizedPlaceholder.classList.add('sized-placeholder');
     pageElement.parentElement.insertBefore(sizedPlaceholder, pageElement);
 
-    this.positionEditableElementOverPageElement();
-
-    // Update the form item's position on scroll and window resize.
-    document.addEventListener('scroll', this.positionEditableElementOverPageElement);
-    window.addEventListener('resize', this.positionEditableElementOverPageElement);
+    this.positionFormItemOverPageElement();
+    document.addEventListener('scroll', this.positionFormItemOverPageElement);
+    window.addEventListener('resize', this.positionFormItemOverPageElement);
 
     // Ensure the sizedPlaceholder height stays in sync with the formItem height.
     // As items are added or removed from the form item via ajax, the sizedPlaceholder
@@ -201,23 +198,23 @@ export class FieldPluginBase {
   }
 
   /**
-   * Replace form item with markup.
+   * Replace form item with page element.
    *
-   * Moves a form item back to the form from the main page area.
+   * Moves a form item back to the form in the sidebar from the main page area.
    *
    * @param EditableElement
    *   The element being edited.
    */
-  replaceEditableElementWithMarkup(EditableElement) {
-    document.removeEventListener('scroll', this.positionEditableElementOverPageElement);
-    window.removeEventListener('resize', this.positionEditableElementOverPageElement);
+  replaceFormItemWithPageElement(EditableElement) {
+    document.removeEventListener('scroll', this.positionFormItemOverPageElement);
+    window.removeEventListener('resize', this.positionFormItemOverPageElement);
 
     const pageElement = EditableElement.getPageElementHandle();
     const formItem = EditableElement.getFormItemHandle();
 
     formItem.removeAttribute('style');
     formItem.classList.remove('edit-plus-editing');
-    const sizedPlaceholder = document.querySelector('#' + utils.getSizedPlaceholderId(EditableElement));
+    const sizedPlaceholder = document.querySelector('#' + EditableElement.getSizedPlaceholderId());
     if (sizedPlaceholder) {
       sizedPlaceholder.remove();
     }
@@ -227,18 +224,18 @@ export class FieldPluginBase {
   }
 
   /**
-   * Position editable element over page element.
+   * Position form item over page element.
    *
-   * The editable element is position: fixed over the placeholder. The
+   * The form item is position: fixed over the placeholder. The
    * placeholder not only pushes content further down the page as if the
    * editable element is in place there, but it also gives us the dimensions that
    * the editable element should have.
    */
-  positionEditableElementOverPageElement() {
+  positionFormItemOverPageElement() {
     const EditableElement = Drupal.EditPlus.CurrentlyEditingElement;
     const formItem = EditableElement.getFormItemHandle();
     const popOutWidth = EditableElement.getFormItemWrapper().dataset.popOutWidth ?? 200;
-    const rectangle = document.querySelector('#' + utils.getSizedPlaceholderId(EditableElement)).getBoundingClientRect();
+    const rectangle = document.querySelector('#' + EditableElement.getSizedPlaceholderId()).getBoundingClientRect();
 
     formItem.style.position = 'fixed';
 
@@ -276,7 +273,7 @@ export class FieldPluginBase {
    * sidebar.
    *
    * @returns {string[]}
-   *   An array of selectors that will not cause the current form item to loose
+   *   An array of selectors that will not cause the current form item to lose
    *   focus if clicked.
    */
   getFocusedSelectors() {
diff --git a/js/edit_plus/fields/inline-editor.js b/js/edit_plus/plugins/inline-editor.js
similarity index 93%
rename from js/edit_plus/fields/inline-editor.js
rename to js/edit_plus/plugins/inline-editor.js
index f8b6568..e9cfd74 100644
--- a/js/edit_plus/fields/inline-editor.js
+++ b/js/edit_plus/plugins/inline-editor.js
@@ -39,16 +39,17 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
       if (ckeditor5Id) {
         const editor = Drupal.EditPlus.Ckeditor5Instances.get(ckeditor5Id);
         if (editor) {
+          // Normally you'd call editor.focus() here, but it's not playing
+          // nice with Safari. Let's manually fire the event.
           setTimeout(() => {
-            // Normally you'd call editor.focus() here, but it's not playing
-            // nice with safari. Let's manually fire the event.
             editor.ui.focusTracker.isFocused = true;
             editor.editing.view.document.fire('focus');
           }, 0);
         } else {
           // The editor hasn't been built yet because the form was just loaded.
           // Remember that this element needs focus and focus it after the editor
-          // has been built.
+          // has been attached.
+          // @see attachEditor.
           Drupal.EditPlus.FocusInlineEditor = ckeditor5Id;
         }
       } else {
@@ -72,7 +73,7 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
       if (data !== originalData) {
         pageElement.innerHTML = textArea.innerText = data;
       }
-      this.replaceEditableElementWithMarkup(EditableElement);
+      this.replaceFormItemWithPageElement(EditableElement);
       if (data !== originalData) {
         entityForm.updateTempstore(EditableElement, data.length === 0);
       }
@@ -141,9 +142,10 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
   /**
    * Focus Inline Editor
    *
-   * After replacePageMarkupWithEditableElement
-   * I think it's because the inline editor is attached with a promise so we can't immediately focus it in the instance that the form item was clicked, the form loaded,
-   * the editor attached, then we need to remember what was clicked so we can focus it once it has been instantiated.
+   * The scenario is that a user clicks on an editable element > the form is
+   * retrieved > the element is focused, but actually the CKEditor hasn't been
+   * asynchronously attached yet, so this is a flag to the attacher that when
+   * this CKEditor is attached it needs focus immediately.
    */
   Drupal.EditPlus.FocusInlineEditor = null;
 
@@ -153,7 +155,8 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
   Drupal.behaviors.EditPlusInlineEditors = {
     attach: (context, settings) => {
       once('EditPlusInlineEdit', '[data-inline-editor-for]', context).forEach(formatSelector => {
-        // Attach the Inline Editor.
+
+        // Attach the Inline Editor or reveal the text area.
         const textAreaId = '#' + formatSelector.dataset.inlineEditorFor;
         const markupElement = document.querySelector(textAreaId).closest('.edit-plus-form-item').querySelector('.edit-plus-inline-edit');
         Drupal.behaviors.EditPlusInlineEditors.showInputElement(markupElement, formatSelector.value);
@@ -168,8 +171,8 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
             const inlineEditElement = formItem.querySelector('.edit-plus-inline-edit');
             const ckeditor5Id = inlineEditElement.dataset.ckeditor5Id;
 
-            // Update the appropriate things before switching formats to prevent
-            // data loss.
+            // Update the textarea and inlineEditElement (markupElement) before
+            // switching formats to prevent data loss.
             if (ckeditor5Id) {
               const editor = Drupal.EditPlus.Ckeditor5Instances.get(ckeditor5Id);
               if (editor) {
@@ -201,7 +204,7 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
     /**
      * Show input element.
      *
-     * Either reveals the textarea or builds the Inline Editor depending on the
+     * Either reveals the textarea or builds the Inline Editor based on the
      * field formatter.
      *
      * @param element
@@ -270,16 +273,15 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
             Drupal.EditPlus.Ckeditor5Instances.set(id, editor);
             const formItem = editor.sourceElement.closest('.edit-plus-form-item');
 
-
             // Does this editor need focus right away? If the CKEditor was the
             // first thing that was clicked that loaded the form, we should focus
             // the editor as soon as it's created.
             if (id === Drupal.EditPlus.FocusInlineEditor) {
-              Drupal.EditPlus.FocusInlineEditor = null;
               // Normally you'd call editor.focus() here, but it's not playing
               // nice with safari. Let's manually fire the event.
               editor.ui.focusTracker.isFocused = true;
               editor.editing.view.document.fire('focus');
+              Drupal.EditPlus.FocusInlineEditor = null;
 
               // Remember the editors original state so we can detect if it has
               // changed and trigger a tempstore update.
diff --git a/js/edit_plus/fields/media.js b/js/edit_plus/plugins/media.js
similarity index 95%
rename from js/edit_plus/fields/media.js
rename to js/edit_plus/plugins/media.js
index ad76d3e..527db92 100644
--- a/js/edit_plus/fields/media.js
+++ b/js/edit_plus/plugins/media.js
@@ -21,7 +21,7 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
       const formItemWrapper = EditableElement.getFormItemWrapper();
       const newValue = formItemWrapper.querySelector('.edit-plus-field-value img')?.src ?? null;
 
-      this.replaceEditableElementWithMarkup(EditableElement);
+      this.replaceFormItemWithPageElement(EditableElement);
       if (newValue && this.originalValue !== newValue) {
         entityForm.updateTempstore(EditableElement, newValue.length === 0);
       }
diff --git a/js/edit_plus/fields/textfield.js b/js/edit_plus/plugins/textfield.js
similarity index 93%
rename from js/edit_plus/fields/textfield.js
rename to js/edit_plus/plugins/textfield.js
index f820026..cd15321 100644
--- a/js/edit_plus/fields/textfield.js
+++ b/js/edit_plus/plugins/textfield.js
@@ -9,7 +9,7 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
 
     supportedWidgets = ['string_textfield'];
 
-    replacePageMarkupWithEditableElement(EditableElement) {
+    replacePageElementWithFormItem(EditableElement) {
       const pageElement = EditableElement.getPageElementHandle();
       pageElement.setAttribute('contenteditable', true);
       pageElement.classList.add('edit-plus-text-editing');
@@ -28,7 +28,7 @@ export default function ($ = jQuery, Drupal, once, dropZones) {
       pageElement.focus();
     }
 
-    replaceEditableElementWithMarkup(EditableElement) {
+    replaceFormItemWithPageElement(EditableElement) {
       const pageElement = EditableElement.getPageElementHandle();
       if (pageElement) {
         pageElement.removeAttribute('contenteditable');
diff --git a/js/edit_plus/utilities.js b/js/edit_plus/utilities.js
deleted file mode 100644
index 1fabe5c..0000000
--- a/js/edit_plus/utilities.js
+++ /dev/null
@@ -1,162 +0,0 @@
-import * as formatterPropertyMap from './formatter-property-map.js';
-
-/**
- * Parse markup ID.
- *
- * @param id
- *   The Entity Plus ID on the rendered field value.
- *
- * @returns {{elementId, langcode: *, fieldName: *, mainProperty: *, delta: *, entityTypeId: *, entityId: *, widget: *, viewMode: *, fieldType: *}}
- *   The elementInfo object.
- */
-export const parseMarkupId = (id) => {
-  const parts = id.split('::');
-  return {
-    entityTypeId: parts[0],
-    entityId: parts[1],
-    fieldName: parts[2],
-    delta: parts[3],
-    langcode: parts[4],
-    viewMode: parts[5],
-    fieldType: parts[6],
-    fieldFormatter: parts[7],
-    mainProperty: parts[8],
-    elementId: id,
-  };
-}
-
-export const parseEntityWrapperId = (id) => {
-  const parts = id.split('::');
-  return {
-    entityTypeId: parts[0],
-    entityId: parts[1],
-    viewMode: parts[2],
-    bundle: parts[3],
-  };
-}
-
-/**
- * Parse Form Item ID.
- *
- * @param id
- *
- * @returns {{fieldName: *, delta: *, property: *, entityTypeId: *, entityId: *}}
- */
-export const parseFormItemId = (id) => {
-  const parts = id.split('::');
-  return {
-    entityTypeId: parts[0],
-    entityId: parts[1],
-    fieldName: parts[2],
-    delta: parts[3],
-    property: parts[4],
-  };
-}
-
-/**
- * Get Form Item Wrapper Id.
- *
- * @param elementInfo
- *   The elementInfo object returned from parseMarkupId.
- *
- * @returns {string}
- *   The form item ID.
- */
-export const getFormItemWrapperId = (elementInfo) => {
-  return [
-    elementInfo.entityTypeId,
-    elementInfo.entityId,
-    elementInfo.fieldName,
-    formatterPropertyMap.getProperty(elementInfo),
-  ].join('::');
-}
-
-/**
- * Get Form Item Id.
- *
- * @param elementInfo
- *   The elementInfo object returned from parseMarkupId.
- *
- * @returns {string}
- *   The form item ID.
- */
-export const getFormItemId = (elementInfo) => {
-  return [
-    elementInfo.entityTypeId,
-    elementInfo.entityId,
-    elementInfo.fieldName,
-    elementInfo.delta,
-    formatterPropertyMap.getProperty(elementInfo),
-  ].join('::');
-}
-
-export const getSizedPlaceholderId = (EditableElement) => {
-  return 'sized-placeholder-' + EditableElement.info.elementId.replace(/::/g, '-');
-}
-
-/**
- * Get markup item.
- *
- * @param formItem
- *   The form item.
- *
- * @returns {Element|null}
- *   The markup item.
- */
-
-// @todo Use page element instead.
-export const getMarkupItem = (formItem) => {
-  if (!formItem.classList.contains('edit-plus-form-item')) {
-    formItem = formItem.querySelector('.edit-plus-form-item');
-  }
-
-  if (!formItem) {
-    return null;
-  }
-
-  return document.querySelector('[data-edit-plus-page-element-id="' + formItem.dataset.editPlusFormItemId + '"]');
-}
-
-export const getPageElement = (element) => {
-  const wrapper = element.closest('[data-edit-plus-page-element-edit-plus-id]')
-  if (wrapper) {
-    return document.querySelector('[data-edit-plus-id="' + wrapper.dataset.editPlusPageElementEditPlusId + '"]');
-  }
-
-  // Inline Editor
-  let formItem = element.closest('.edit-plus-form-item');
-
-  // @todo This is a candidate for removal. I think this is covered by data-edit-plus-page-element-edit-plus-id now.
-  // Some parts of Media Library widget.
-  // if (!formItem) {
-  //   formItem = element.querySelector('.edit-plus-form-item');
-  // }
-
-  return document.querySelector('[data-edit-plus-page-element-id="' + formItem.dataset.editPlusFormItemId + '"]');
-}
-
-
-/**
- * Get Form ID.
- *
- * @param elementInfo
- *   The elementInfo object returned from parseMarkupId.
- *
- * @returns {string}
- *   The Edit Plus form ID
- */
-export const getFormId = (elementInfo) => {
-  return [
-    elementInfo.entityTypeId,
-    elementInfo.entityId,
-  ].join('::');
-}
-
-export const getPageElementWrapperId = (elementInfo) => {
-  return [
-    elementInfo.entityTypeId,
-    elementInfo.entityId,
-    elementInfo.fieldName,
-    elementInfo.mainProperty,
-  ].join('::');
-}
diff --git a/modules/edit_plus_lb/edit_plus_lb.services.yml b/modules/edit_plus_lb/edit_plus_lb.services.yml
index f27fb5c..d682c79 100644
--- a/modules/edit_plus_lb/edit_plus_lb.services.yml
+++ b/modules/edit_plus_lb/edit_plus_lb.services.yml
@@ -1,6 +1,7 @@
 services:
+  _defaults:
+    autoconfigure: true
+    autowire: true
+
   edit_plus_lb.section_component_build_render_array:
     class: Drupal\edit_plus_lb\EventSubscriber\SectionComponentBuildRenderArray
-    arguments: ['@current_user']
-    tags:
-      - { name: event_subscriber }
diff --git a/modules/edit_plus_lb/src/Form/UpdateBlockForm.php b/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
index eb4954c..ef452e8 100644
--- a/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
+++ b/modules/edit_plus_lb/src/Form/UpdateBlockForm.php
@@ -53,7 +53,6 @@ class UpdateBlockForm extends UpdateBlockFormBase implements EntityFormInterface
     protected EventDispatcherInterface $dispatcher,
     protected RendererInterface $renderer,
     protected Request $request,
-    protected Ui $ui,
     $block_manager,
     $uuid,
   ) {
@@ -74,7 +73,6 @@ class UpdateBlockForm extends UpdateBlockFormBase implements EntityFormInterface
       $container->get('event_dispatcher'),
       $container->get('renderer'),
       $container->get('request_stack')->getCurrentRequest(),
-      $container->get('edit_plus.ui'),
       $container->get('plugin.manager.block'),
       $container->get('uuid'),
     );
@@ -161,10 +159,12 @@ class UpdateBlockForm extends UpdateBlockFormBase implements EntityFormInterface
   protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state) {
     $response = new AjaxResponse();
 
-    $entity = $form_state->getStorage()['section_storage']->getContextValue('entity');
-    $this->buildBottomBar($entity, $response);
     $this->renderMessages($response);
     $this->updatePage($response, $form, $form_state);
+    // Check if a field was just emptied.
+    if (!empty($form_state->getUserInput()['settings']['block_form']['empty_field'])) {
+      $this->updateForm($response, $form, $form_state);
+    }
 
     return $response;
   }
@@ -283,9 +283,6 @@ class UpdateBlockForm extends UpdateBlockFormBase implements EntityFormInterface
     $form['settings']['label']['#wrapper_attributes']['class'][] = 'edit-plus-form-item';
     $form['settings']['label']['#wrapper_attributes']['class'][] = 'edit-plus-hidden';
     $form['settings']['label']['#attributes']['data-edit-plus-input'] =  $form_item_id;;
-//    if (empty($form['settings']['label']['#attributes']['id'])) {
-//      $form['settings']['label']['#attributes']['id'] = Html::getUniqueId($form_item_id);
-//    }
     $form['settings']['label_wrapper'] = [
       '#type' => 'container',
       'label' => $form['settings']['label'],
diff --git a/src/Controller/MultipleEntityFormController.php b/src/Controller/MultipleEntityFormController.php
index 32f8fea..4ccc2ba 100644
--- a/src/Controller/MultipleEntityFormController.php
+++ b/src/Controller/MultipleEntityFormController.php
@@ -2,22 +2,21 @@
 
 namespace Drupal\edit_plus\Controller;
 
-use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
+use Drupal\edit_plus\Ui;
 use Drupal\Core\Form\FormState;
 use Drupal\Core\Ajax\AjaxResponse;
-use Drupal\Core\Ajax\InvokeCommand;
 use Drupal\Core\Ajax\AppendCommand;
-use Drupal\Core\Form\FormStateInterface;
 use Drupal\edit_plus\EditPlusFormTrait;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Controller\ControllerBase;
-use Drupal\edit_plus\Ui;
-use Drupal\field_sample_value\SampleValueEntityGeneratorInterface;
-use Psr\EventDispatcher\EventDispatcherInterface;
 use Symfony\Component\HttpFoundation\Request;
 use Drupal\edit_plus\EditPlusTempstoreRepository;
+use Psr\EventDispatcher\EventDispatcherInterface;
+use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\field_sample_value\SampleValueEntityGeneratorInterface;
 use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
 
 /**
@@ -29,7 +28,6 @@ final class MultipleEntityFormController extends ControllerBase {
   use StringTranslationTrait;
 
   public function __construct(
-    protected Ui $ui,
     protected Request $request,
     protected EventDispatcherInterface $dispatcher,
     protected ArgumentResolverInterface $argumentResolver,
@@ -40,7 +38,6 @@ final class MultipleEntityFormController extends ControllerBase {
 
   public static function create(ContainerInterface $container) {
     return new static (
-      $container->get('edit_plus.ui'),
       $container->get('request_stack')->getCurrentRequest(),
       $container->get('event_dispatcher'),
       $container->get('http_kernel.controller.argument_resolver'),
diff --git a/src/EditPlusFormTrait.php b/src/EditPlusFormTrait.php
index 7388121..661a3b6 100644
--- a/src/EditPlusFormTrait.php
+++ b/src/EditPlusFormTrait.php
@@ -49,8 +49,6 @@ trait EditPlusFormTrait {
       '#value' => NULL,
     ];
 
-    // @todo Shouldn't adding this button just be a FieldAttributes event?
-    // @todo or is it special for some reason?
     foreach ($entity->getFieldDefinitions() as $field_name => $field_definition) {
       if (!empty($form[$field_name])) {
         $this->addFieldToPageButton($form, $entity, $field_name);
@@ -155,7 +153,6 @@ trait EditPlusFormTrait {
     $response = new AjaxResponse();
     $this->updatePage($response, $form, $form_state);
     $this->updateForm($response, $form, $form_state);
-    $this->buildBottomBar($this->getMainEntity($form, $form_state), $response);
     $this->renderMessages($response);
 
     return $response;
@@ -176,16 +173,17 @@ trait EditPlusFormTrait {
     $view_mode = $this->getViewMode($form, $form_state, $entity);
     $view_mode = _toolbar_plus_get_view_mode($entity, $view_mode);
     $content = $this->entityContent($form, $form_state, $view_mode);
+    $input = $this->getUserInput($form_state);
     if (!empty($content['component']['content']['#view_mode']) && $content['component']['content']['#view_mode'] !== $view_mode) {
       // It's possible that the view mode was changed in this update. $view_mode
       // needs to remain as it was for replacing the old content on the page, but
       // let's update the view mode for passing it on down the line.
       if (!empty($form['settings']['block_form']['view_mode']['#value'])) {
-        // @todo This only covers inline blocks I think since it looks for the new view mode in component > content > #view_mode. Ensure that we don't need to cover other situations like entity forms.
+        // @todo This only covers inline blocks I think since it looks for the new view mode in component > content > #view_mode.
+        // Ensure that we don't need to cover other situations like entity forms.
         $form['settings']['block_form']['view_mode']['#value'] = $content['component']['content']['#view_mode'];
       }
 
-      $input = $this->getUserInput($form_state);
       $input['view_mode'] = $content['component']['content']['#view_mode'];
       $form_state->setUserInput($input);
     }
@@ -287,21 +285,6 @@ trait EditPlusFormTrait {
       ];
   }
 
-  /**
-   * Build bottom bar.
-   *
-   * @param \Drupal\Core\Entity\EntityInterface $entity
-   *   The entity to build the bottom bar for.
-   * @param \Drupal\Core\Ajax\AjaxResponse $response
-   *   The ajax response.
-   *
-   * @throws \Drupal\Core\Entity\EntityMalformedException
-   */
-  public function buildBottomBar(EntityInterface $entity, AjaxResponse $response) {
-    $page_bottom['bottom_bar']['edit_plus_bottom_bar'] = $this->ui->buildBottomBar([$entity->getEntityTypeId() . '.' . $entity->id() => $entity], $entity->toUrl()->toString());
-    $response->addCommand(new InsertCommand('#toolbar-plus-bottom-bar', $page_bottom));
-  }
-
   public function renderMessages(AjaxResponse $response) {
     $status_messages = ['#type' => 'status_messages'];
     $messages = $this->renderer->renderRoot($status_messages);
diff --git a/src/EventSubscriber/AttributesTrait.php b/src/EventSubscriber/AttributesTrait.php
index c4547b2..6eff7dc 100644
--- a/src/EventSubscriber/AttributesTrait.php
+++ b/src/EventSubscriber/AttributesTrait.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace Drupal\edit_plus\EventSubscriber;
 
 use Drupal\edit_plus\Event\FieldAttributes;
+use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
 
 trait AttributesTrait {
 
@@ -14,11 +15,20 @@ trait AttributesTrait {
     if (empty($form_display))  {
       // Must not be an entity form, load the form display.
       $entity = $event->getEntity();
-      // @todo Use an abstract getter method for dependency injection.
-      $form_display = \Drupal::service('entity_display.repository')->getFormDisplay($entity->getEntityTypeId(), $entity->bundle());
+      $form_display = static::getEntityDisplayRepository()->getFormDisplay($entity->getEntityTypeId(), $entity->bundle());
     }
 
     return $form_display->getComponent($field_name)['type'];
   }
 
+  /**
+   * Get entity display repository.
+   *
+   * @return \Drupal\Core\Entity\EntityDisplayRepositoryInterface
+   *   The entity display repository service.
+   */
+  protected static function getEntityDisplayRepository(): EntityDisplayRepositoryInterface {
+    return \Drupal::service('entity_display.repository');
+  }
+
 }
diff --git a/src/EventSubscriber/DefaultFieldAttributes.php b/src/EventSubscriber/DefaultFieldAttributes.php
index 2f5ac1b..6fbe0b9 100644
--- a/src/EventSubscriber/DefaultFieldAttributes.php
+++ b/src/EventSubscriber/DefaultFieldAttributes.php
@@ -4,13 +4,14 @@ declare(strict_types=1);
 
 namespace Drupal\edit_plus\EventSubscriber;
 
-use Drupal\Core\Entity\Entity\EntityViewDisplay;
 use Drupal\Core\Render\Element;
 use Drupal\Core\Template\Attribute;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\edit_plus\Event\FieldAttributes;
 use Drupal\edit_plus\Event\FieldProperties;
+use Drupal\Core\Entity\Entity\EntityViewDisplay;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
@@ -20,6 +21,10 @@ class DefaultFieldAttributes implements EventSubscriberInterface {
 
   use AttributesTrait;
 
+  public function __construct(
+    protected EventDispatcherInterface $eventDispatcher,
+  ) {}
+
   /**
    * Add form item attributes.
    *
@@ -59,8 +64,7 @@ class DefaultFieldAttributes implements EventSubscriberInterface {
 
     $properties = $entity->getFieldDefinition($field_name)->getFieldStorageDefinition()->getPropertyNames();
     // Allow modules to specify custom properties.
-    // @todo Use an abstract getter method for dependency injection.
-    $properties = \Drupal::service('event_dispatcher')->dispatch(new FieldProperties($entity, $field_name, $properties), FieldProperties::class)->getProperties();
+    $properties = $this->eventDispatcher->dispatch(new FieldProperties($entity, $field_name, $properties), FieldProperties::class)->getProperties();
 
     if (!empty($form_item['widget']['#theme']) && $form_item['widget']['#theme'] === 'field_multiple_value_form') {
       foreach (Element::children($form_item['widget']) as $delta) {
diff --git a/src/EventSubscriber/HandleFieldAttribute.php b/src/EventSubscriber/HandleFieldAttribute.php
index 2a3d695..9ae00e3 100644
--- a/src/EventSubscriber/HandleFieldAttribute.php
+++ b/src/EventSubscriber/HandleFieldAttribute.php
@@ -17,7 +17,6 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  */
 class HandleFieldAttribute implements EventSubscriberInterface {
 
-
   public function addFormItemAttributesAlter(FieldAttributes $event) {
     $form = $event->getForm();
     $entity = $event->getEntity();
diff --git a/src/EventSubscriber/PopOutWidthFieldAttribute.php b/src/EventSubscriber/PopOutWidthFieldAttribute.php
index 53b87fc..cccc6df 100644
--- a/src/EventSubscriber/PopOutWidthFieldAttribute.php
+++ b/src/EventSubscriber/PopOutWidthFieldAttribute.php
@@ -12,13 +12,12 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  */
 class PopOutWidthFieldAttribute implements EventSubscriberInterface {
 
-
   public function addFormItemAttributesAlter(FieldAttributes $event) {
     $form = $event->getForm();
     $field_name = $event->getFieldName();
     $form_item = &$form[$field_name];
     if (empty($form_item['#attributes']['data-pop-out-width'])) {
-      $form_item['#attributes']['data-pop-out-width'] = '300';
+      $form_item['#attributes']['data-pop-out-width'] = '200';
     }
 
     $event->setForm($form);
diff --git a/src/Form/InlineEntityFormAlter.php b/src/Form/InlineEntityFormAlter.php
index 19d34b5..fa21ca3 100644
--- a/src/Form/InlineEntityFormAlter.php
+++ b/src/Form/InlineEntityFormAlter.php
@@ -44,7 +44,6 @@ class InlineEntityFormAlter implements EntityFormInterface {
     protected ModuleHandlerInterface $moduleHandler,
     protected RendererInterface $renderer,
     protected RequestStack $requestStack,
-    protected Ui $ui,
   ) {
     $this->request = $this->requestStack->getCurrentRequest();
   }
@@ -102,7 +101,6 @@ class InlineEntityFormAlter implements EntityFormInterface {
       $this->updateForm($response, $form, $form_state);
     }
 
-    $this->buildBottomBar($entity, $response);
     $this->renderMessages($response);
 
     $response->addCommand(new InvokeCommand(NULL, 'editPlusIsDoneUpdating'));
diff --git a/src/Form/ViewsFormMediaLibraryWidgetAlter.php b/src/Form/ViewsFormMediaLibraryWidgetAlter.php
index ee97bea..b530814 100644
--- a/src/Form/ViewsFormMediaLibraryWidgetAlter.php
+++ b/src/Form/ViewsFormMediaLibraryWidgetAlter.php
@@ -3,14 +3,13 @@
 namespace Drupal\edit_plus\Form;
 
 use Drupal\Core\Ajax\AjaxResponse;
-use Drupal\Core\Ajax\CloseDialogCommand;
 use Drupal\Core\Ajax\InvokeCommand;
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Drupal\edit_plus\EventSubscriber\HandleFieldAttribute;
+use Drupal\Core\Ajax\CloseDialogCommand;
 use Drupal\media_library\MediaLibraryState;
-use Drupal\media_library\Plugin\views\field\MediaLibrarySelectForm;
 use Symfony\Component\HttpFoundation\Request;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\media_library\Plugin\views\field\MediaLibrarySelectForm;
 
 /**
  */
diff --git a/src/Ui.php b/src/Ui.php
deleted file mode 100644
index 6edd929..0000000
--- a/src/Ui.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-
-namespace Drupal\edit_plus;
-
-use Drupal\Core\Url;
-
-class Ui {
-
-  function buildBottomBar($actively_used_tempstore_entities, $destination) {
-    // @todo deprecated, remove.
-    return [
-      'toolbar_plus' => [
-        '#type' => 'container',
-        '#attributes' => [
-          'id' => 'toolbar-plus-bottom-bar',
-        ],
-        'edit_plus_bottom_bar' => [
-          '#type' => 'container',
-          '#attributes' => [
-            'id' => 'edit-plus-bottom-bar',
-          ],
-          'save' => [
-            '#type' => 'link',
-            '#title' => t('Save'),
-            '#url' => Url::fromRoute('edit_plus.tempstore.save', [
-              'entities' => implode('::', array_keys($actively_used_tempstore_entities)),
-            ], [
-              'query' => ['destination' => $destination]
-            ]),
-            '#attributes' => [
-              'class' => ['button'],
-            ],
-          ],
-          'discard_changes' => [
-            '#type' => 'link',
-            '#title' => t('Discard changes'),
-            '#url' => Url::fromRoute('edit_plus.tempstore.delete', [
-              'entities' => implode('::', array_keys($actively_used_tempstore_entities)),
-            ], [
-              'query' => ['destination' => $destination]
-            ]),
-            '#attributes' => [
-              'class' => ['button'],
-            ],
-          ],
-        ],
-      ],
-    ];
-  }
-
-}
-- 
GitLab