diff --git a/README.md b/README.md
index d3f2ae9b3f2ed44f0e96134a4c24e00bdd471411..3fdd1f816674189d19a3f75fe214ce986f55bfe6 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
 ## AIDmi - AI, describe my image!
 
-AIDmi provides a button that will use an AI API to send an image to return a detailed description.
+AIDmi provides a button that will use an AI API 
+to send an image to return a detailed description.
 
 ## Installation
 
@@ -9,10 +10,10 @@ Enable aidmi.
 drush en aidmi
 
 - Configure the settings under Configure > Web services > AIDmi Settings
-    - Select API: Only Gemini at the moment.
-    - API Key Input Method: API key in Settings or File Path
-        - File Path is recommended. Make sure you save the file outside of web/ (Example on page)
-    - API Instructions: Default text provided that is sent to AI for image description.
+- Select API: Only Gemini at the moment.
+- API Key Input Method: API key in Settings or File Path
+- File Path is recommended outside of web/ (Example on page)
+- API Instructions: Default text provided for AI image description.
 
 ## Development of CKEditor5 Button
 
diff --git a/aidmi.libraries.yml b/aidmi.libraries.yml
index 3595812ae8255fad9f8b88558021b250951c84ed..8d7775b33f21e456c36a750762d341345d90de41 100644
--- a/aidmi.libraries.yml
+++ b/aidmi.libraries.yml
@@ -11,4 +11,3 @@ aidmi_ckeditor:
     - core/drupal.dialog.ajax
     - core/jquery
     - core/once
-    
\ No newline at end of file
diff --git a/aidmi.module b/aidmi.module
index e19114d4d2a5c12a2ec9b9e88ff59f1f1daa00a0..bc5c233402639e9c3253beb6ceb8527c8ca9a485 100644
--- a/aidmi.module
+++ b/aidmi.module
@@ -1,14 +1,18 @@
 <?php
 
-use Drupal\editor\Entity\Editor;
-use Drupal\ckeditor5\Plugin\CKEditor5PluginDefinition;
+/**
+ * @file
+ * AIDmi - AI, describe my image.
+ */
+
+use Drupal\Core\Routing\RouteMatchInterface;
 
 /**
  * Implements hook_help().
  *
  * Provides a help page for the module.
  */
-function aidmi_help($route_name, \Drupal\Core\Routing\RouteMatchInterface $route_match) {
+function aidmi_help($route_name, RouteMatchInterface $route_match) {
   switch ($route_name) {
     case 'help.page.aidmi':
       return '<p>' . t('The AIDmi module allows users to upload images and get 508-compliant image descriptions generated by AI.') . '</p>';
diff --git a/aidmi.routing.yml b/aidmi.routing.yml
index 947661737127b4e344ec3a6ea4868c711b2150c5..fd3cb6377020d4e30b8bd9f7a841bcc03877ed21 100644
--- a/aidmi.routing.yml
+++ b/aidmi.routing.yml
@@ -25,4 +25,4 @@ aidmi.describe_content_ajax:
   requirements:
     _permission: 'access content'
   options:
-    _format: 'json'
\ No newline at end of file
+    _format: 'json'
diff --git a/aidmi.services.yml b/aidmi.services.yml
index 2ac0a30dce8ed5fa2011770c41081d88e1313d51..a325e26b83d0a3f615b2c5141e57cb6a991724bf 100644
--- a/aidmi.services.yml
+++ b/aidmi.services.yml
@@ -6,4 +6,3 @@ services:
   aidmi.aidmicontroller:
     class: 'Drupal\aidmi\Controller\AidmiController'
     arguments: ['@aidmi.gemini_ai_service']
-      
\ No newline at end of file
diff --git a/css/aidmi.css b/css/aidmi.css
index b1ae4ed21a66aec866d5e60cc0d7345ccfb1da48..a17ce663fe39389b0eda293381dffa6df0a8303e 100644
--- a/css/aidmi.css
+++ b/css/aidmi.css
@@ -1,63 +1,63 @@
 .aidmi-dialog {
-    height: auto;
-  }
+  height: auto;
+}
 
 .aidmi-dialog button {
-    margin-right: 10px;
+  margin-right: 10px;
 }
 
-.aidmi-dialog-content-scrollable {    
-    max-height: 300px;    
-    overflow-y: auto;     
-    padding: 10px;        
+.aidmi-dialog-content-scrollable {
+  max-height: 300px;
+  overflow-y: auto;
+  padding: 10px;
 }
 
 .aidmi-dialog-subtitle {
-    font-size: 0.9em;
-    color: #666; 
-    margin-top: -10px; 
-    margin-bottom: 10px;
+  font-size: 0.9em;
+  color: #666;
+  margin-top: -10px;
+  margin-bottom: 10px;
 }
 
 .aidmi-dialog-image {
-    max-width: 100%; 
-    max-height: 400px;
+  max-width: 100%;
+  max-height: 400px;
 }
 
 .aidmi-highlight-missing {
-    border: 2px solid red;
-    padding: 10px;
-    margin: 10px 0;
+  border: 2px solid red;
+  padding: 10px;
+  margin: 10px 0;
 }
 
 .aidmi-dialog-textarea {
-    resize: vertical;
-    width: 100%;
+  resize: vertical;
+  width: 100%;
 }
 
 .ckeditor5-toolbar-button-aidmi {
-    background-image: url(../icons/aidmi.svg);
+  background-image: url(../icons/aidmi.svg);
 }
 
 /* CKEditor5 AIDmi icon */
 .aidmi-icon-str1 {
-    stroke:#2D2A2B;
-    stroke-width:0.83;
-    stroke-miterlimit:2.61313;
+  stroke: #2d2a2b;
+  stroke-width: 0.83;
+  stroke-miterlimit: 2.61313;
 }
 .aidmi-icon-str0 {
-    stroke:black;
-    stroke-width:0.83;
-    stroke-miterlimit:2.61313;
+  stroke: black;
+  stroke-width: 0.83;
+  stroke-miterlimit: 2.61313;
 }
 .aidmi-icon-fil2 {
-    fill:none;
+  fill: none;
 }
 .aidmi-icon-fil0 {
-    fill:none;
-    fill-rule:nonzero;
+  fill: none;
+  fill-rule: nonzero;
 }
 .aidmi-icon-fil1 {
-    fill:black;
-    fill-rule:nonzero;
-}
\ No newline at end of file
+  fill: black;
+  fill-rule: nonzero;
+}
diff --git a/js/aidmi.dialog.js b/js/aidmi.dialog.js
index 57847d5d4d8dd44717ed7f8c3225263e8c5b89ca..5323a73bfd1d8f3453f0f5fc091daa4b92d296b0 100644
--- a/js/aidmi.dialog.js
+++ b/js/aidmi.dialog.js
@@ -1,78 +1,77 @@
 (function ($, Drupal) {
-    Drupal.behaviors.aidmiDialog = {
-        attach: function (context, settings) {    
-        Drupal.aidmi = Drupal.aidmi || {};            
-        
-        Drupal.aidmi.aidmiDialog = function (content, callback) {
-            let aidmiEditedText;
-            // Create a temporary container to hold the content.
-            const tempElement = document.createElement('div');
-            tempElement.setAttribute('role', 'dialog');
-            tempElement.setAttribute('aria-labelledby', 'aidmi-dialog-title');
-            tempElement.setAttribute('aria-describedby', 'aidmi-dialog-description');
-            tempElement.setAttribute('aria-modal', 'true'); // Ensures screen readers treat the dialog as a modal.
+  Drupal.behaviors.aidmiDialog = {
+    attach: function (context, settings) {
+      Drupal.aidmi = Drupal.aidmi || {};
 
-            // Set title text.
-            let tempETitle = 'AIDmi Description';
-            let tempESubTitle = 'Please evaluate and edit the description as needed.';
+      Drupal.aidmi.aidmiDialog = function (content, callback) {
+        let aidmiEditedText;
+        // Create a temporary container to hold the content.
+        const tempElement = document.createElement('div');
+        tempElement.setAttribute('role', 'dialog');
+        tempElement.setAttribute('aria-labelledby', 'aidmi-dialog-title');
+        tempElement.setAttribute('aria-describedby', 'aidmi-dialog-description');
+        tempElement.setAttribute('aria-modal', 'true'); // Ensures screen readers treat the dialog as a modal.
 
-            // Create dialog content with a textarea for editing.
-            tempElement.innerHTML = `
-            <div>
-                <h2 id="aidmi-dialog-title">${Drupal.t(tempETitle)}</h2>
-                <p id="aidmi-dialog-subtitle" class="aidmi-dialog-subtitle">${Drupal.t(tempESubTitle)}</p>
-                <textarea id="aidmi-dialog-textarea" class="aidmi-dialog-textarea" rows="6" style="width: 100%;">${Drupal.t(content)}</textarea>
-            </div>`;
+        // Set title text.
+        let tempETitle = 'AIDmi Description';
+        let tempESubTitle = 'Please evaluate and edit the description as needed.';
 
-            // Store the element that triggered the dialog, to return focus later.
-            const previousFocus = document.activeElement;
+        // Create dialog content with a textarea for editing.
+        tempElement.innerHTML = `
+          <div>
+            <h2 id="aidmi-dialog-title">${Drupal.t(tempETitle)}</h2>
+            <p id="aidmi-dialog-subtitle" class="aidmi-dialog-subtitle">${Drupal.t(tempESubTitle)}</p>
+            <textarea id="aidmi-dialog-textarea" class="aidmi-dialog-textarea" rows="6" style="width: 100%;">${Drupal.t(content)}</textarea>
+          </div>`;
 
-            // Use the Drupal off-canvas dialog to show the content.
-            const options = {
-            dialogClass: 'aidmi-dialog',
-            title: tempETitle,
-            width: '400px',
-            buttons: [
-                {
-                text: Drupal.t('Insert Text'),
-                click: function () {
-                    // Get the value from the textarea.
-                    aidmiEditedText = document.getElementById('aidmi-dialog-textarea').value;
+        // Store the element that triggered the dialog, to return focus later.
+        const previousFocus = document.activeElement;
 
-                    // Pass the modified text back through the callback.
-                    callback(aidmiEditedText);
+        // Use the Drupal off-canvas dialog to show the content.
+        const options = {
+          dialogClass: 'aidmi-dialog',
+          title: tempETitle,
+          width: '400px',
+          buttons: [
+            {
+              text: Drupal.t('Insert Text'),
+              click: function () {
+                // Get the value from the textarea.
+                aidmiEditedText = document.getElementById('aidmi-dialog-textarea').value;
 
-                    // Close the dialog.
-                    dialogInstance.close();
-                }
-                },
-                {
-                text: Drupal.t('Cancel'),
-                click: function () {
-                    // Return false when Cancel is clicked.
-                    callback(false);
+                // Pass the modified text back through the callback.
+                callback(aidmiEditedText);
 
-                    // Close the dialog.
-                    dialogInstance.close();
-                }
-                }
-            ],
-            close: function () {
-                // Return focus to the original element when the dialog is closed.
-                previousFocus.focus();
-            }
-            };
+                // Close the dialog.
+                dialogInstance.close();
+              }
+            },
+            {
+              text: Drupal.t('Cancel'),
+              click: function () {
+                // Return false when Cancel is clicked.
+                callback(false);
 
-            // Open the dialog using Drupal's dialog API.
-            const dialogInstance = Drupal.dialog(tempElement, options);
-            dialogInstance.showModal();
+                // Close the dialog.
+                dialogInstance.close();
+              }
+            }
+          ],
+          close: function () {
+            // Return focus to the original element when the dialog is closed.
+            previousFocus.focus();
+          }
+        };
 
-            // Set focus on the textarea for screen readers.
-            const textareaElement = document.getElementById('aidmi-dialog-textarea');
-            textareaElement.setAttribute('tabindex', '-1');
-            textareaElement.focus();
+        // Open the dialog using Drupal's dialog API.
+        const dialogInstance = Drupal.dialog(tempElement, options);
+        dialogInstance.showModal();
 
-        }
+        // Set focus on the textarea for screen readers.
+        const textareaElement = document.getElementById('aidmi-dialog-textarea');
+        textareaElement.setAttribute('tabindex', '-1');
+        textareaElement.focus();
+      };
     }
   };
-})(jQuery, Drupal);
\ No newline at end of file
+})(jQuery, Drupal);
diff --git a/js/build/aidmiPlugin.js b/js/build/aidmiPlugin.js
index 7ee8d72b8044624ff2e1659440430b43fa2216c4..ee768b05d43b49b3e4e2f93a9ad45fb0ef9d8883 100644
--- a/js/build/aidmiPlugin.js
+++ b/js/build/aidmiPlugin.js
@@ -1 +1 @@
-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.aidmiPlugin=t())}(self,(()=>(()=>{var e={"ckeditor5/src/core.js":(e,t,i)=>{e.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/ui.js":(e,t,i)=>{e.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},t={};function i(a){var n=t[a];if(void 0!==n)return n.exports;var l=t[a]={exports:{}};return e[a](l,l.exports,i),l.exports}i.d=(e,t)=>{for(var a in t)i.o(t,a)&&!i.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var a={};return(()=>{"use strict";i.d(a,{default:()=>d});var e=i("ckeditor5/src/core.js"),t=i("ckeditor5/src/ui.js");const n='<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="20px" height="20px" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"\r\nviewBox="0 0 20 20"\r\n xmlns:xlink="http://www.w3.org/1999/xlink">\r\n <g id="aidmi-icon-layer">\r\n  <metadata id="aidmi-icon"/>\r\n  <path class="aidmi-icon-fil0 aidmi-icon-str0" d="M8.62 17.95c-0.58,0.31 -1.2,0.42 -1.84,0.33 -0.63,-0.08 -1.23,-0.36 -1.7,-0.83l-0.01 -0.01 -0.01 0c-0.75,-0.09 -1.4,-0.45 -1.87,-0.96 -0.46,-0.52 -0.74,-1.18 -0.74,-1.91l0 -0.07 -0.02 -0.01c-0.02,-0.01 -0.04,-0.02 -0.05,-0.03 -0.1,-0.05 -0.17,-0.1 -0.27,-0.17 -0.09,-0.07 -0.18,-0.14 -0.27,-0.21 -0.07,-0.06 -0.13,-0.12 -0.19,-0.18 -0.11,-0.11 -0.21,-0.23 -0.3,-0.35 -0.14,-0.19 -0.26,-0.39 -0.36,-0.6 0,-0.02 -0.01,-0.03 -0.02,-0.03 -0.07,-0.18 -0.13,-0.36 -0.17,-0.55 -0.06,-0.24 -0.09,-0.49 -0.09,-0.73 0,-0.2 0.02,-0.38 0.06,-0.57 0.04,-0.22 0.1,-0.44 0.18,-0.64l0.02 -0.04c0.16,-0.37 0.39,-0.72 0.68,-1.02l0.01 -0.01 0 -0.03c-0.1,-0.4 -0.1,-0.81 -0.02,-1.21 0.03,-0.1 0.06,-0.19 0.09,-0.28 0.03,-0.09 0.05,-0.18 0.09,-0.26 0.15,-0.35 0.37,-0.67 0.66,-0.94l0.01 -0.01 0 -0.03c-0.11,-0.67 0.04,-1.32 0.37,-1.87 0.34,-0.56 0.86,-1 1.52,-1.25l0.02 0 0 -0.02c0.45,-1.12 1.56,-1.86 2.81,-1.86 0.45,0.01 0.88,0.1 1.27,0.29l0 15.62c0.01,0.17 0.05,0.31 0.14,0.44z"/>\r\n  <path class="aidmi-icon-fil0 aidmi-icon-str0" d="M15.59 16.48c-0.47,0.51 -1.12,0.87 -1.87,0.96l-0.01 0 -0.01 0.01c-0.47,0.47 -1.07,0.75 -1.7,0.83 -0.64,0.09 -1.26,-0.02 -1.84,-0.32 0.09,-0.14 0.14,-0.28 0.14,-0.45l0 -15.62c0.4,-0.19 0.82,-0.28 1.27,-0.29 1.25,0 2.37,0.74 2.81,1.86l0.01 0.02 0.02 0c0.66,0.25 1.18,0.69 1.51,1.25 0.34,0.55 0.48,1.2 0.38,1.87l0 0.03 0.01 0.01c0.28,0.27 0.51,0.59 0.66,0.94 0.04,0.08 0.06,0.17 0.09,0.27 0.03,0.09 0.06,0.18 0.08,0.27 0.09,0.4 0.09,0.81 -0.01,1.21l-0.01 0.03 0.02 0.01c0.29,0.3 0.52,0.65 0.68,1.03l0.01 0.03c0.06,0.14 0.11,0.28 0.14,0.43 -0.68,-0.48 -1.54,-0.85 -2.54,-0.85 -2.77,0 -4.44,2.84 -4.44,2.84l-0.01 0.02 0.01 0.03c0,0 1.67,2.83 4.44,2.83 0.23,0 0.46,-0.02 0.68,-0.06 -0.13,0.3 -0.31,0.57 -0.52,0.81z"/>\r\n  <path class="aidmi-icon-fil1" d="M20.04 12.85c0,0 -1.73,-2.91 -4.61,-2.91 -2.89,0 -4.62,2.91 -4.62,2.91 0,0 1.73,2.91 4.62,2.91 2.88,0 4.61,-2.91 4.61,-2.91zm-8.55 0c0.28,-0.39 0.6,-0.75 0.96,-1.08 0.74,-0.68 1.75,-1.3 2.98,-1.3 1.22,0 2.24,0.62 2.98,1.3 0.36,0.33 0.68,0.69 0.96,1.08 -0.04,0.05 -0.07,0.1 -0.12,0.15 -0.19,0.26 -0.47,0.59 -0.84,0.93 -0.74,0.68 -1.76,1.3 -2.98,1.3 -1.23,0 -2.24,-0.62 -2.98,-1.3 -0.36,-0.33 -0.68,-0.69 -0.96,-1.08l0 0z"/>\r\n  <path class="aidmi-icon-fil1" d="M15.63 11.82c-0.88,0 -1.43,0.84 -0.99,1.51 0.21,0.31 0.58,0.5 0.99,0.5 0.89,0 1.44,-0.84 1,-1.51 -0.21,-0.31 -0.59,-0.5 -1,-0.5zm-1.6 1c0,-1.08 1.34,-1.76 2.41,-1.22 0.49,0.25 0.8,0.72 0.8,1.22 0,1.09 -1.34,1.77 -2.41,1.23 -0.5,-0.26 -0.8,-0.72 -0.8,-1.23z"/>\r\n  <line class="aidmi-icon-fil2 aidmi-icon-str1" x1="12.92" y1="8.92" x2="17.64" y2= "16.79" />\r\n </g>\r\n</svg>\r\n';class l extends e.Plugin{init(){const e=this.editor,i=e.plugins.get("SourceEditing");e.ui.componentFactory.add("aidmi",(a=>{const l=new t.ButtonView(a);return l.set({label:e.t("AI, describe my image!"),icon:n,tooltip:!0,isEnabled:!i||!i.isSourceEditingMode}),this.listenTo(l,"execute",(async()=>{try{l.label="Processing...",l.isEnabled=!1,l.icon='<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" style="color:#1C2033" class="h-full w-full">\n    <rect width="20" height="20" x="0" y="0" rx="0" fill="transparent" stroke="transparent" stroke-width="0" stroke-opacity="0%" paint-order="stroke" /><svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewBox="0 0 20 20" fill="#1C2033" x="0" y="0" role="img" style="display:inline-block;vertical-align:middle">\n        <g fill="#1C2033">\n            <rect width="6" height="14" x="1" y="4" fill="currentColor">\n                <animate id="svgSpinnersBarsScaleFade0" fill="freeze" attributeName="y" begin="0;svgSpinnersBarsScaleFade1.end-0.25s" dur="0.75s" values="1;5" />\n                <animate fill="freeze" attributeName="height" begin="0;svgSpinnersBarsScaleFade1.end-0.25s" dur="0.75s" values="22;14" />\n                <animate fill="freeze" attributeName="opacity" begin="0;svgSpinnersBarsScaleFade1.end-0.25s" dur="0.75s" values="1;.2" />\n            </rect>\n            <rect width="6" height="14" x="9" y="4" fill="currentColor" opacity=".4">\n                <animate fill="freeze" attributeName="y" begin="svgSpinnersBarsScaleFade0.begin+0.15s" dur="0.75s" values="1;5" />\n                <animate fill="freeze" attributeName="height" begin="svgSpinnersBarsScaleFade0.begin+0.15s" dur="0.75s" values="22;14" />\n                <animate fill="freeze" attributeName="opacity" begin="svgSpinnersBarsScaleFade0.begin+0.15s" dur="0.75s" values="1;.2" />\n            </rect>\n            <rect width="6" height="14" x="17" y="4" fill="currentColor" opacity=".3">\n                <animate id="svgSpinnersBarsScaleFade1" fill="freeze" attributeName="y" begin="svgSpinnersBarsScaleFade0.begin+0.3s" dur="0.75s" values="1;5" />\n                <animate fill="freeze" attributeName="height" begin="svgSpinnersBarsScaleFade0.begin+0.3s" dur="0.75s" values="22;14" />\n                <animate fill="freeze" attributeName="opacity" begin="svgSpinnersBarsScaleFade0.begin+0.3s" dur="0.75s" values="1;.2" />\n            </rect>\n        </g>\n    </svg>\n</svg>';let t=null,i=null,a=this._aidmiJSONImages(e.getData());a.length>0&&(t=await this._aidmiContentAjax(e.getData(),a)),t&&t.length>0&&(i=JSON.parse(t),this._openDialog(e,i,a))}catch(e){console.log("Error:",e)}finally{l.label="AI, describe my image!",l.icon=n,l.isEnabled=!0}})),e.model.document.on("change:data",(()=>{const t=this._aidmiJSONImages(e.getData()).length>0;l.isEnabled=t&&(!i||!i.isSourceEditingMode)})),i&&i.on("change:isSourceEditingMode",((e,t,i)=>{l.isEnabled=!i})),l}))}_aidmiJSONImages(e){const t=document.createElement("div");t.innerHTML=e;let i=t.querySelectorAll("img, drupal-media"),a=[];return i.forEach((e=>{let t={"data-entity-uuid":e.getAttribute("data-entity-uuid"),type:e.tagName.toLowerCase()};a.push(t)})),a}_aidmiContentAjax(e,t){const i=jQuery;return new Promise(((a,n)=>{i.ajax({url:"/admin/aidmi/describe-content-ajax",method:"POST",data:{content:e,imagesJSON:JSON.stringify(t)},success:function(e){a(e)},error:function(e,t,i){n(i)}})}))}_openDialog(e,t,i){const a=document.createElement("div");a.setAttribute("role","dialog"),a.setAttribute("aria-labelledby","aidmi-dialog-title"),a.setAttribute("aria-describedby","aidmi-dialog-description"),a.setAttribute("aria-modal","true");a.innerHTML=`<p id="aidmi-dialog-subtitle" class="aidmi-dialog-subtitle">${Drupal.t("Please evaluate and edit the description as needed.")}</p>`;let n=0;t.forEach((e=>{e.images&&Array.isArray(e.images)&&(n+=e.images.length)})),t.forEach((e=>{e.images&&Array.isArray(e.images)&&e.images.forEach((e=>{let t="";t+=`<div class="image-option-group" id="option-group-${e["data-entity-uuid"]}">`,t+=`\n                        \x3c!-- Image Display --\x3e\n                        <img class="aidmi-dialog-image" data-entity-uuid="${e["data-entity-uuid"]}" src="${e.src}" alt="${Drupal.t(e.before_alt)}" />`;let i=!1,n="Current Alt Tag - Read only",l=e.before_alt;(!l||l.length<6)&&(n+=" (Option disabled since alt is either blank or too short)",i=!0),t+=`\n                        \x3c!-- Current Alt Tag Section --\x3e\n                        <div>\n                            <label for="aidmi-alt-old-${e["data-entity-uuid"]}" class="aidmi-dialog-label">\n                                <input type="radio" name="aidmi-alt-selection-${e["data-entity-uuid"]}" id="aidmi-alt-old-${e["data-entity-uuid"]}" value="current" aria-labelledby="label-old-${e["data-entity-uuid"]}" ${i?"disabled":""} required/>\n                                <span id="label-old-${e["data-entity-uuid"]}">${Drupal.t(n)}</span>\n                            </label>`,i||(t+=`\n                                <textarea id="aidmi-dialog-textarea-oldalt-${e["data-entity-uuid"]}" class="aidmi-dialog-textarea" rows="3" aria-labelledby="label-old-${e["data-entity-uuid"]}" readonly="readonly">${Drupal.t(e.before_alt)}</textarea>`),t+="\n                        </div>",t+=`\n                        \x3c!-- Suggested Alt Tag Section --\x3e\n                        <div>\n                            <label for="aidmi-alt-new-${e["data-entity-uuid"]}" class="aidmi-dialog-label">\n                                <input type="radio" name="aidmi-alt-selection-${e["data-entity-uuid"]}" id="aidmi-alt-new-${e["data-entity-uuid"]}" value="suggested" aria-labelledby="label-new-${e["data-entity-uuid"]}" required>\n                                <span id="label-new-${e["data-entity-uuid"]}">${Drupal.t("Suggested Alt Tag - Review and modify as required")}</span>\n                            </label>\n                            <textarea id="aidmi-dialog-textarea-newalt-${e["data-entity-uuid"]}" class="aidmi-dialog-textarea" rows="3" aria-labelledby="label-new-${e["data-entity-uuid"]}">${Drupal.t(e.recommendation)}</textarea>\n                        </div>`,t+=`\n                        \x3c!-- Set as Decorative Image --\x3e\n                        <div>\n                            <label for="aidmi-alt-decorative-${e["data-entity-uuid"]}" class="aidmi-dialog-label">\n                                <input type="radio" name="aidmi-alt-selection-${e["data-entity-uuid"]}" id="aidmi-alt-decorative-${e["data-entity-uuid"]}" value="decorative" aria-labelledby="label-decorative-${e["data-entity-uuid"]}" required>\n                                <span id="label-decorative-${e["data-entity-uuid"]}">${Drupal.t("Set as Decorative Image")}</span>\n                            </label>\n                        </div>`,t+="</div><hr/>",a.innerHTML+=t}))}));const l={dialogClass:"aidmi-dialog",title:"AIDmi Description",resizable:!0,width:"700px",buttons:[{text:Drupal.t("Insert Text"),class:"aidmi-insert-button",click:()=>{const i=this._collectSelections(t);i?(this._modifyImagesInContent(e,i),r.close()):alert(Drupal.t("Please select an option for each image before inserting."))}},{text:Drupal.t("Cancel"),click:function(){r.close()}}]},r=Drupal.dialog(a,l);r.showModal(),document.querySelectorAll('input[type="radio"]').forEach((e=>{e.addEventListener("change",(e=>{const t=e.target.name.replace("aidmi-alt-selection-","option-group-");document.getElementById(t).classList.remove("aidmi-highlight-missing")}))})),document.querySelector('input[type="radio"]').focus()}_collectSelections(e){let t=!0;const i=[];return e.forEach((e=>{e.images&&Array.isArray(e.images)&&e.images.forEach((e=>{const a=e["data-entity-uuid"],n=document.querySelector(`input[name="aidmi-alt-selection-${a}"]:checked`);if(n){const e=n.value;let t="";"current"===e?t=document.getElementById(`aidmi-dialog-textarea-oldalt-${a}`).value:"suggested"===e&&(t=document.getElementById(`aidmi-dialog-textarea-newalt-${a}`).value),i.push({uuid:a,altText:"decorative"===e?"":t,isDecorative:"decorative"===e})}else t=!1,document.getElementById(`option-group-${a}`).classList.add("aidmi-highlight-missing")}))})),t?i:null}_modifyImagesInContent(e,t){let i=e.getData();const a=document.createElement("div");a.innerHTML=i,t.forEach((e=>{const t=a.querySelector(`[data-entity-uuid="${e.uuid}"]`);t?e.isDecorative?(t.setAttribute("alt",""),t.setAttribute("role","presentation")):(t.setAttribute("alt",e.altText),t.removeAttribute("role")):console.warn(`Image with UUID ${e.uuid} not found in content.`)})),e.setData(a.innerHTML),e.editing.view.document.fire("change:data")}}class r extends e.Plugin{static get requires(){return[l]}static get pluginName(){return"AIDmi"}}const d={AIDmi:r}})(),a=a.default})()));
\ No newline at end of file
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.aidmiPlugin=t())}(self,(()=>(()=>{var e={"ckeditor5/src/core.js":(e,t,i)=>{e.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/ui.js":(e,t,i)=>{e.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},t={};function i(a){var n=t[a];if(void 0!==n)return n.exports;var l=t[a]={exports:{}};return e[a](l,l.exports,i),l.exports}i.d=(e,t)=>{for(var a in t)i.o(t,a)&&!i.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var a={};return(()=>{"use strict";i.d(a,{default:()=>d});var e=i("ckeditor5/src/core.js"),t=i("ckeditor5/src/ui.js");const n='<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="20px" height="20px" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"\r\nviewBox="0 0 20 20"\r\n xmlns:xlink="http://www.w3.org/1999/xlink">\r\n <g id="aidmi-icon-layer">\r\n  <metadata id="aidmi-icon"/>\r\n  <path class="aidmi-icon-fil0 aidmi-icon-str0" d="M8.62 17.95c-0.58,0.31 -1.2,0.42 -1.84,0.33 -0.63,-0.08 -1.23,-0.36 -1.7,-0.83l-0.01 -0.01 -0.01 0c-0.75,-0.09 -1.4,-0.45 -1.87,-0.96 -0.46,-0.52 -0.74,-1.18 -0.74,-1.91l0 -0.07 -0.02 -0.01c-0.02,-0.01 -0.04,-0.02 -0.05,-0.03 -0.1,-0.05 -0.17,-0.1 -0.27,-0.17 -0.09,-0.07 -0.18,-0.14 -0.27,-0.21 -0.07,-0.06 -0.13,-0.12 -0.19,-0.18 -0.11,-0.11 -0.21,-0.23 -0.3,-0.35 -0.14,-0.19 -0.26,-0.39 -0.36,-0.6 0,-0.02 -0.01,-0.03 -0.02,-0.03 -0.07,-0.18 -0.13,-0.36 -0.17,-0.55 -0.06,-0.24 -0.09,-0.49 -0.09,-0.73 0,-0.2 0.02,-0.38 0.06,-0.57 0.04,-0.22 0.1,-0.44 0.18,-0.64l0.02 -0.04c0.16,-0.37 0.39,-0.72 0.68,-1.02l0.01 -0.01 0 -0.03c-0.1,-0.4 -0.1,-0.81 -0.02,-1.21 0.03,-0.1 0.06,-0.19 0.09,-0.28 0.03,-0.09 0.05,-0.18 0.09,-0.26 0.15,-0.35 0.37,-0.67 0.66,-0.94l0.01 -0.01 0 -0.03c-0.11,-0.67 0.04,-1.32 0.37,-1.87 0.34,-0.56 0.86,-1 1.52,-1.25l0.02 0 0 -0.02c0.45,-1.12 1.56,-1.86 2.81,-1.86 0.45,0.01 0.88,0.1 1.27,0.29l0 15.62c0.01,0.17 0.05,0.31 0.14,0.44z"/>\r\n  <path class="aidmi-icon-fil0 aidmi-icon-str0" d="M15.59 16.48c-0.47,0.51 -1.12,0.87 -1.87,0.96l-0.01 0 -0.01 0.01c-0.47,0.47 -1.07,0.75 -1.7,0.83 -0.64,0.09 -1.26,-0.02 -1.84,-0.32 0.09,-0.14 0.14,-0.28 0.14,-0.45l0 -15.62c0.4,-0.19 0.82,-0.28 1.27,-0.29 1.25,0 2.37,0.74 2.81,1.86l0.01 0.02 0.02 0c0.66,0.25 1.18,0.69 1.51,1.25 0.34,0.55 0.48,1.2 0.38,1.87l0 0.03 0.01 0.01c0.28,0.27 0.51,0.59 0.66,0.94 0.04,0.08 0.06,0.17 0.09,0.27 0.03,0.09 0.06,0.18 0.08,0.27 0.09,0.4 0.09,0.81 -0.01,1.21l-0.01 0.03 0.02 0.01c0.29,0.3 0.52,0.65 0.68,1.03l0.01 0.03c0.06,0.14 0.11,0.28 0.14,0.43 -0.68,-0.48 -1.54,-0.85 -2.54,-0.85 -2.77,0 -4.44,2.84 -4.44,2.84l-0.01 0.02 0.01 0.03c0,0 1.67,2.83 4.44,2.83 0.23,0 0.46,-0.02 0.68,-0.06 -0.13,0.3 -0.31,0.57 -0.52,0.81z"/>\r\n  <path class="aidmi-icon-fil1" d="M20.04 12.85c0,0 -1.73,-2.91 -4.61,-2.91 -2.89,0 -4.62,2.91 -4.62,2.91 0,0 1.73,2.91 4.62,2.91 2.88,0 4.61,-2.91 4.61,-2.91zm-8.55 0c0.28,-0.39 0.6,-0.75 0.96,-1.08 0.74,-0.68 1.75,-1.3 2.98,-1.3 1.22,0 2.24,0.62 2.98,1.3 0.36,0.33 0.68,0.69 0.96,1.08 -0.04,0.05 -0.07,0.1 -0.12,0.15 -0.19,0.26 -0.47,0.59 -0.84,0.93 -0.74,0.68 -1.76,1.3 -2.98,1.3 -1.23,0 -2.24,-0.62 -2.98,-1.3 -0.36,-0.33 -0.68,-0.69 -0.96,-1.08l0 0z"/>\r\n  <path class="aidmi-icon-fil1" d="M15.63 11.82c-0.88,0 -1.43,0.84 -0.99,1.51 0.21,0.31 0.58,0.5 0.99,0.5 0.89,0 1.44,-0.84 1,-1.51 -0.21,-0.31 -0.59,-0.5 -1,-0.5zm-1.6 1c0,-1.08 1.34,-1.76 2.41,-1.22 0.49,0.25 0.8,0.72 0.8,1.22 0,1.09 -1.34,1.77 -2.41,1.23 -0.5,-0.26 -0.8,-0.72 -0.8,-1.23z"/>\r\n  <line class="aidmi-icon-fil2 aidmi-icon-str1" x1="12.92" y1="8.92" x2="17.64" y2= "16.79" />\r\n </g>\r\n</svg>\r\n';class l extends e.Plugin{init(){const e=this.editor,i=e.plugins.get("SourceEditing");e.ui.componentFactory.add("aidmi",(a=>{const l=new t.ButtonView(a);return l.set({label:e.t("AI, describe my image!"),icon:n,tooltip:!0,isEnabled:!i||!i.isSourceEditingMode}),this.listenTo(l,"execute",(async()=>{try{l.label="Processing...",l.isEnabled=!1,l.icon='<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" style="color:#1C2033" class="h-full w-full">\n    <rect width="20" height="20" x="0" y="0" rx="0" fill="transparent" stroke="transparent" stroke-width="0" stroke-opacity="0%" paint-order="stroke" /><svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewBox="0 0 20 20" fill="#1C2033" x="0" y="0" role="img" style="display:inline-block;vertical-align:middle">\n        <g fill="#1C2033">\n            <rect width="6" height="14" x="1" y="4" fill="currentColor">\n                <animate id="svgSpinnersBarsScaleFade0" fill="freeze" attributeName="y" begin="0;svgSpinnersBarsScaleFade1.end-0.25s" dur="0.75s" values="1;5" />\n                <animate fill="freeze" attributeName="height" begin="0;svgSpinnersBarsScaleFade1.end-0.25s" dur="0.75s" values="22;14" />\n                <animate fill="freeze" attributeName="opacity" begin="0;svgSpinnersBarsScaleFade1.end-0.25s" dur="0.75s" values="1;.2" />\n            </rect>\n            <rect width="6" height="14" x="9" y="4" fill="currentColor" opacity=".4">\n                <animate fill="freeze" attributeName="y" begin="svgSpinnersBarsScaleFade0.begin+0.15s" dur="0.75s" values="1;5" />\n                <animate fill="freeze" attributeName="height" begin="svgSpinnersBarsScaleFade0.begin+0.15s" dur="0.75s" values="22;14" />\n                <animate fill="freeze" attributeName="opacity" begin="svgSpinnersBarsScaleFade0.begin+0.15s" dur="0.75s" values="1;.2" />\n            </rect>\n            <rect width="6" height="14" x="17" y="4" fill="currentColor" opacity=".3">\n                <animate id="svgSpinnersBarsScaleFade1" fill="freeze" attributeName="y" begin="svgSpinnersBarsScaleFade0.begin+0.3s" dur="0.75s" values="1;5" />\n                <animate fill="freeze" attributeName="height" begin="svgSpinnersBarsScaleFade0.begin+0.3s" dur="0.75s" values="22;14" />\n                <animate fill="freeze" attributeName="opacity" begin="svgSpinnersBarsScaleFade0.begin+0.3s" dur="0.75s" values="1;.2" />\n            </rect>\n        </g>\n    </svg>\n</svg>';let t=null,i=null,a=this._aidmiJSONImages(e.getData());a.length>0&&(t=await this._aidmiContentAjax(e.getData(),a)),t&&t.length>0&&(i=JSON.parse(t),this._openDialog(e,i,a))}catch(e){console.log("Error:",e)}finally{l.label="AI, describe my image!",l.icon=n,l.isEnabled=!0}})),e.model.document.on("change:data",(()=>{const t=this._aidmiJSONImages(e.getData()).length>0;l.isEnabled=t&&(!i||!i.isSourceEditingMode)})),i&&i.on("change:isSourceEditingMode",((e,t,i)=>{l.isEnabled=!i})),l}))}_aidmiJSONImages(e){const t=document.createElement("div");t.innerHTML=e;let i=t.querySelectorAll("img, drupal-media"),a=[];return i.forEach((e=>{let t={"data-entity-uuid":e.getAttribute("data-entity-uuid"),type:e.tagName.toLowerCase()};a.push(t)})),a}_aidmiContentAjax(e,t){const i=jQuery;return new Promise(((a,n)=>{i.ajax({url:"/admin/aidmi/describe-content-ajax",method:"POST",data:{content:e,imagesJSON:JSON.stringify(t)},success:function(e){a(e)},error:function(e,t,i){n(i)}})}))}_openDialog(e,t,i){const a=document.createElement("div");a.setAttribute("role","dialog"),a.setAttribute("aria-labelledby","aidmi-dialog-title"),a.setAttribute("aria-describedby","aidmi-dialog-description"),a.setAttribute("aria-modal","true");a.innerHTML=`<p id="aidmi-dialog-subtitle" class="aidmi-dialog-subtitle">${Drupal.t("Please evaluate and edit the description as needed.")}</p>`;let n=0;t.forEach((e=>{e.images&&Array.isArray(e.images)&&(n+=e.images.length)})),t.forEach((e=>{e.images&&Array.isArray(e.images)&&e.images.forEach((e=>{let t="";t+=`<div class="image-option-group" id="option-group-${e["data-entity-uuid"]}">`,t+=`\n            \x3c!-- Image Display --\x3e\n            <img class="aidmi-dialog-image" data-entity-uuid="${e["data-entity-uuid"]}" src="${e.src}" alt="${Drupal.t(e.before_alt)}" />`;let i=!1,n="Current Alt Tag - Read only",l=e.before_alt;(!l||l.length<6)&&(n+=" (Option disabled since alt is either blank or too short)",i=!0),t+=`\n            \x3c!-- Current Alt Tag Section --\x3e\n            <div>\n              <label for="aidmi-alt-old-${e["data-entity-uuid"]}" class="aidmi-dialog-label">\n                <input type="radio" name="aidmi-alt-selection-${e["data-entity-uuid"]}" id="aidmi-alt-old-${e["data-entity-uuid"]}" value="current" aria-labelledby="label-old-${e["data-entity-uuid"]}" ${i?"disabled":""} required/>\n                <span id="label-old-${e["data-entity-uuid"]}">${Drupal.t(n)}</span>\n              </label>`,i||(t+=`\n                <textarea id="aidmi-dialog-textarea-oldalt-${e["data-entity-uuid"]}" class="aidmi-dialog-textarea" rows="3" aria-labelledby="label-old-${e["data-entity-uuid"]}" readonly="readonly">${Drupal.t(e.before_alt)}</textarea>`),t+="\n            </div>",t+=`\n            \x3c!-- Suggested Alt Tag Section --\x3e\n            <div>\n              <label for="aidmi-alt-new-${e["data-entity-uuid"]}" class="aidmi-dialog-label">\n                <input type="radio" name="aidmi-alt-selection-${e["data-entity-uuid"]}" id="aidmi-alt-new-${e["data-entity-uuid"]}" value="suggested" aria-labelledby="label-new-${e["data-entity-uuid"]}" required>\n                <span id="label-new-${e["data-entity-uuid"]}">${Drupal.t("Suggested Alt Tag - Review and modify as required")}</span>\n              </label>\n              <textarea id="aidmi-dialog-textarea-newalt-${e["data-entity-uuid"]}" class="aidmi-dialog-textarea" rows="3" aria-labelledby="label-new-${e["data-entity-uuid"]}">${Drupal.t(e.recommendation)}</textarea>\n            </div>`,t+=`\n            \x3c!-- Set as Decorative Image --\x3e\n            <div>\n              <label for="aidmi-alt-decorative-${e["data-entity-uuid"]}" class="aidmi-dialog-label">\n                <input type="radio" name="aidmi-alt-selection-${e["data-entity-uuid"]}" id="aidmi-alt-decorative-${e["data-entity-uuid"]}" value="decorative" aria-labelledby="label-decorative-${e["data-entity-uuid"]}" required>\n                <span id="label-decorative-${e["data-entity-uuid"]}">${Drupal.t("Set as Decorative Image")}</span>\n              </label>\n            </div>`,t+="</div><hr/>",a.innerHTML+=t}))}));const l={dialogClass:"aidmi-dialog",title:"AIDmi Description",resizable:!0,width:"700px",buttons:[{text:Drupal.t("Insert Text"),class:"aidmi-insert-button",click:()=>{const i=this._collectSelections(t);i?(this._modifyImagesInContent(e,i),r.close()):alert(Drupal.t("Please select an option for each image before inserting."))}},{text:Drupal.t("Cancel"),click:function(){r.close()}}]},r=Drupal.dialog(a,l);r.showModal(),document.querySelectorAll('input[type="radio"]').forEach((e=>{e.addEventListener("change",(e=>{const t=e.target.name.replace("aidmi-alt-selection-","option-group-");document.getElementById(t).classList.remove("aidmi-highlight-missing")}))})),document.querySelector('input[type="radio"]').focus()}_collectSelections(e){let t=!0;const i=[];return e.forEach((e=>{e.images&&Array.isArray(e.images)&&e.images.forEach((e=>{const a=e["data-entity-uuid"],n=document.querySelector(`input[name="aidmi-alt-selection-${a}"]:checked`);if(n){const e=n.value;let t="";"current"===e?t=document.getElementById(`aidmi-dialog-textarea-oldalt-${a}`).value:"suggested"===e&&(t=document.getElementById(`aidmi-dialog-textarea-newalt-${a}`).value),i.push({uuid:a,altText:"decorative"===e?"":t,isDecorative:"decorative"===e})}else t=!1,document.getElementById(`option-group-${a}`).classList.add("aidmi-highlight-missing")}))})),t?i:null}_modifyImagesInContent(e,t){let i=e.getData();const a=document.createElement("div");a.innerHTML=i,t.forEach((e=>{const t=a.querySelector(`[data-entity-uuid="${e.uuid}"]`);t?e.isDecorative?(t.setAttribute("alt",""),t.setAttribute("role","presentation")):(t.setAttribute("alt",e.altText),t.removeAttribute("role")):console.warn(`Image with UUID ${e.uuid} not found in content.`)})),e.setData(a.innerHTML),e.editing.view.document.fire("change:data")}}class r extends e.Plugin{static get requires(){return[l]}static get pluginName(){return"AIDmi"}}const d={AIDmi:r}})(),a=a.default})()));
\ No newline at end of file
diff --git a/js/ckeditor5_plugins/aidmiPlugin/src/aidmiui.js b/js/ckeditor5_plugins/aidmiPlugin/src/aidmiui.js
index 84100251a73dac797e1356ea0b5865029e740a32..d07136b589f1e2b540359cee603c42fa153d65ef 100644
--- a/js/ckeditor5_plugins/aidmiPlugin/src/aidmiui.js
+++ b/js/ckeditor5_plugins/aidmiPlugin/src/aidmiui.js
@@ -1,347 +1,346 @@
 import { Plugin } from 'ckeditor5/src/core';
 import {
-    ButtonView,
-    FocusCycler,
-    LabeledFieldView,
-    SwitchButtonView,
-    View,
-    ViewCollection,
-    createLabeledInputText,
-    injectCssTransitionDisabler,
-    submitHandler,
+  ButtonView,
+  FocusCycler,
+  LabeledFieldView,
+  SwitchButtonView,
+  View,
+  ViewCollection,
+  createLabeledInputText,
+  injectCssTransitionDisabler,
+  submitHandler,
 } from 'ckeditor5/src/ui';
 
 import iconAidmi from '../../../../icons/aidmi.svg';
 import iconAidmiLoading from '../../../../icons/aidmi_loading.svg';
 
 export default class AIDmiUI extends Plugin {
-    init() {        
-        const editor = this.editor;
+  init() {        
+    const editor = this.editor;
 
-        // Check if the SourceEditing plugin is available.
-        const sourceEditing = editor.plugins.get('SourceEditing');
+    // Check if the SourceEditing plugin is available.
+    const sourceEditing = editor.plugins.get('SourceEditing');
 
-        // This will register the AIDmi toolbar button.
-        editor.ui.componentFactory.add('aidmi', (locale) => {
-            const button = new ButtonView(locale);
-    
-            // Create the toolbar button.
-            button.set({
-                label: editor.t('AI, describe my image!'),
-                icon: iconAidmi,
-                tooltip: true,
-                isEnabled: !sourceEditing || !sourceEditing.isSourceEditingMode  // Initially disable if in source mode
-            });
-        
-            this.listenTo(button, 'execute', async () => {
-                try {
-                    // Show loading state
-                    button.label = 'Processing...';
-                    button.isEnabled = false; // Disable the button
-
-                    // Change to loading icon.
-                    button.icon = iconAidmiLoading; 
-
-                    let output = null;
-                    let parsedOutput = null;             
-                    let imagesJSON = this._aidmiJSONImages(editor.getData());
-                    if (imagesJSON.length > 0) {
-                        output = await this._aidmiContentAjax(editor.getData(), imagesJSON);
-                    }                    
-                    if (output && output.length > 0) {
-                        parsedOutput = JSON.parse(output);
-                        this._openDialog(editor, parsedOutput, imagesJSON);
-                    }
-                } 
-                catch (error) {
-                    console.log("Error:", error);
-                }
-                finally {
-                    // Restore button state after processing is done
-                    button.label = 'AI, describe my image!';
-
-                    button.icon = iconAidmi; // Restore the original icon
-                    button.isEnabled = true; // Re-enable the button
-                }
-
-            });      
-            
-            // Add a listener to enable or disable the button based on content changes.
-            editor.model.document.on('change:data', () => {
-                // Leverage the _aidmiJSONImages function to check for images in the content
-                const hasImages = this._aidmiJSONImages(editor.getData()).length > 0;
-                button.isEnabled = hasImages && (!sourceEditing || !sourceEditing.isSourceEditingMode);
-            });      
-
-            // Listen for changes in the source editing mode if the plugin is available.
-            if (sourceEditing) {
-                sourceEditing.on('change:isSourceEditingMode', (evt, name, value) => {
-                    button.isEnabled = !value;  // Disable button if in source editing mode.
-                });
-            }
+    // This will register the AIDmi toolbar button.
+    editor.ui.componentFactory.add('aidmi', (locale) => {
+      const button = new ButtonView(locale);
 
-            return button;
-        });
+      // Create the toolbar button.
+      button.set({
+        label: editor.t('AI, describe my image!'),
+        icon: iconAidmi,
+        tooltip: true,
+        isEnabled: !sourceEditing || !sourceEditing.isSourceEditingMode  // Initially disable if in source mode
+      });
 
-    }
+      this.listenTo(button, 'execute', async () => {
+        try {
+          // Show loading state
+          button.label = 'Processing...';
+          button.isEnabled = false; // Disable the button
 
-    _aidmiJSONImages(content) {
-        // Create a temporary DOM element to parse the HTML string
-        const tempDiv = document.createElement('div');
-        tempDiv.innerHTML = content; // Convert the HTML string to DOM elements
-        // Find all images with the class 'aidmi-dialog-image'
-        let images = tempDiv.querySelectorAll('img, drupal-media');
-        
+          // Change to loading icon.
+          button.icon = iconAidmiLoading; 
 
-        // Initialize an empty array to store the JSON data
-        let imageJsonArray = [];
-
-        // Loop through each image and extract 'data-entity-uuid' and 'src'
-        images.forEach((image) => {
-            let imageObject = {
-                "data-entity-uuid": image.getAttribute('data-entity-uuid'),
-                "type": image.tagName.toLowerCase()
-            };
-            
-            // Push the image object to the array
-            imageJsonArray.push(imageObject);
-        });
-        
-        // Convert the array to a JSON string for output or further use
-        return imageJsonArray;
-    }
-
-    _aidmiContentAjax(content, imagesJSON) {   
-        const $ = jQuery;
-        return new Promise((resolve, reject) => {
-            $.ajax({
-                url: '/admin/aidmi/describe-content-ajax',
-                method: 'POST',
-                data: {
-                    content: content,
-                    imagesJSON: JSON.stringify(imagesJSON)
-                },
-                success: function(response) {
-                    resolve(response);
-                },
-                error: function(xhr, status, error) {
-                    reject(error);
-                }
-            });
-        });
-    }
-
-    _openDialog(editor, data, callback) {
-        let aidmiEditedText;
-        // Create a temporary container to hold the content.
-        const tempElement = document.createElement('div');
-        tempElement.setAttribute('role', 'dialog');
-        tempElement.setAttribute('aria-labelledby', 'aidmi-dialog-title');
-        tempElement.setAttribute('aria-describedby', 'aidmi-dialog-description');
-        tempElement.setAttribute('aria-modal', 'true'); // Ensures screen readers treat the dialog as a modal.
-
-        // Set title text.
-        let tempETitle = 'AIDmi Description';
-        let tempESubTitle = 'Please evaluate and edit the description as needed.';
-
-        // Create dialog content with a textarea for editing.
-        tempElement.innerHTML = `<p id="aidmi-dialog-subtitle" class="aidmi-dialog-subtitle">${Drupal.t(tempESubTitle)}</p>`;
-
-        // Variable to store the number of images
-        let imageCount = 0;
-        data.forEach(item => {
-            if (item.images && Array.isArray(item.images)) {
-                imageCount += item.images.length;
-            }
-        });
-        // Loop through the images
-        data.forEach(item => {
-            // If item has an images array, loop through it
-            if (item.images && Array.isArray(item.images)) {
-                item.images.forEach((image) => {
-                    let formImageInnerHTML = '';
-                    // Start of image div alt option area.
-                    formImageInnerHTML += `<div class="image-option-group" id="option-group-${image['data-entity-uuid']}">`;
-                    // Add Image Display.
-                    formImageInnerHTML += `
-                        <!-- Image Display -->
-                        <img class="aidmi-dialog-image" data-entity-uuid="${image['data-entity-uuid']}" src="${image.src}" alt="${Drupal.t(image.before_alt)}" />`;
-                    // Add Current Alt Tag Section.
-                    let imageOldSelectDisabled = false;
-                    let imageLabel = 'Current Alt Tag - Read only';
-                    let imageBeforeAlt = image.before_alt;
-                    if (!imageBeforeAlt || imageBeforeAlt.length < 6) {
-                        // Old alt shouldn't be an allowed option.
-                        imageLabel += ' (Option disabled since alt is either blank or too short)';
-                        imageOldSelectDisabled = true;
-                    }
-                    formImageInnerHTML += `
-                        <!-- Current Alt Tag Section -->
-                        <div>
-                            <label for="aidmi-alt-old-${image['data-entity-uuid']}" class="aidmi-dialog-label">
-                                <input type="radio" name="aidmi-alt-selection-${image['data-entity-uuid']}" id="aidmi-alt-old-${image['data-entity-uuid']}" value="current" aria-labelledby="label-old-${image['data-entity-uuid']}" ${imageOldSelectDisabled ? 'disabled' : ''} required/>
-                                <span id="label-old-${image['data-entity-uuid']}">${Drupal.t(imageLabel)}</span>
-                            </label>`; 
-
-                    // If radio is disabled, don't show the alt textarea.
-                    if (!imageOldSelectDisabled) {
-                        formImageInnerHTML += `
-                                <textarea id="aidmi-dialog-textarea-oldalt-${image['data-entity-uuid']}" class="aidmi-dialog-textarea" rows="3" aria-labelledby="label-old-${image['data-entity-uuid']}" readonly="readonly">${Drupal.t(image.before_alt)}</textarea>`;
-                    }
-                    
-                    formImageInnerHTML += `
-                        </div>`;   
-                    
-                    // Add Suggested Alt Tag Section.
-                    formImageInnerHTML += `
-                        <!-- Suggested Alt Tag Section -->
-                        <div>
-                            <label for="aidmi-alt-new-${image['data-entity-uuid']}" class="aidmi-dialog-label">
-                                <input type="radio" name="aidmi-alt-selection-${image['data-entity-uuid']}" id="aidmi-alt-new-${image['data-entity-uuid']}" value="suggested" aria-labelledby="label-new-${image['data-entity-uuid']}" required>
-                                <span id="label-new-${image['data-entity-uuid']}">${Drupal.t('Suggested Alt Tag - Review and modify as required')}</span>
-                            </label>
-                            <textarea id="aidmi-dialog-textarea-newalt-${image['data-entity-uuid']}" class="aidmi-dialog-textarea" rows="3" aria-labelledby="label-new-${image['data-entity-uuid']}">${Drupal.t(image.recommendation)}</textarea>
-                        </div>`;
-                    // Add Set as Decorative Image.
-                    formImageInnerHTML += `
-                        <!-- Set as Decorative Image -->
-                        <div>
-                            <label for="aidmi-alt-decorative-${image['data-entity-uuid']}" class="aidmi-dialog-label">
-                                <input type="radio" name="aidmi-alt-selection-${image['data-entity-uuid']}" id="aidmi-alt-decorative-${image['data-entity-uuid']}" value="decorative" aria-labelledby="label-decorative-${image['data-entity-uuid']}" required>
-                                <span id="label-decorative-${image['data-entity-uuid']}">${Drupal.t('Set as Decorative Image')}</span>
-                            </label>
-                        </div>`;
-                    // End of image div alt option area.
-                    formImageInnerHTML += `</div><hr/>`;
-                    
-                    // Insert it.
-                    tempElement.innerHTML += formImageInnerHTML;
-                });
-            }            
-        });
+          let output = null;
+          let parsedOutput = null;             
+          let imagesJSON = this._aidmiJSONImages(editor.getData());
+          if (imagesJSON.length > 0) {
+            output = await this._aidmiContentAjax(editor.getData(), imagesJSON);
+          }                    
+          if (output && output.length > 0) {
+            parsedOutput = JSON.parse(output);
+            this._openDialog(editor, parsedOutput, imagesJSON);
+          }
+        } 
+        catch (error) {
+          console.log("Error:", error);
+        }
+        finally {
+          // Restore button state after processing is done
+          button.label = 'AI, describe my image!';
 
-        // Use the Drupal off-canvas dialog to show the content.
-        const options = {
-            dialogClass: 'aidmi-dialog',
-            title: tempETitle,
-            resizable: true,
-            width: '700px',
-            buttons: [
-                {
-                    text: Drupal.t('Insert Text'),
-                    class: 'aidmi-insert-button', // Add a class to the insert button for reference
-                    click: () => {
-                        // Validate all selections before inserting text
-                        const selections = this._collectSelections(data);
-                        if (selections) {
-                            // Modify the images in the editor content based on the selections
-                            this._modifyImagesInContent(editor, selections);
-                            dialogInstance.close();
-                        } else {
-                            // Show a message if validation fails
-                            alert(Drupal.t('Please select an option for each image before inserting.'));
-                        }
-                    }
-                },
-                {
-                    text: Drupal.t('Cancel'),
-                    click: function () {
-                        // Close the dialog.
-                        dialogInstance.close();
-                    }
-                }
-            ]
-        };
-
-        // Open the dialog using Drupal's dialog API.
-        const dialogInstance = Drupal.dialog(tempElement, options);
-        dialogInstance.showModal();
-
-        // Add event listeners to all radio buttons to validate the selection and remove highlights
-        document.querySelectorAll('input[type="radio"]').forEach(radio => {
-            radio.addEventListener('change', (event) => {
-                const groupId = event.target.name.replace('aidmi-alt-selection-', 'option-group-');
-                // Remove the highlight class when a selection is made
-                document.getElementById(groupId).classList.remove('aidmi-highlight-missing');
-            });
+          button.icon = iconAidmi; // Restore the original icon
+          button.isEnabled = true; // Re-enable the button
+        }
+
+      });      
+
+      // Add a listener to enable or disable the button based on content changes.
+      editor.model.document.on('change:data', () => {
+        // Leverage the _aidmiJSONImages function to check for images in the content
+        const hasImages = this._aidmiJSONImages(editor.getData()).length > 0;
+        button.isEnabled = hasImages && (!sourceEditing || !sourceEditing.isSourceEditingMode);
+      });      
+
+      // Listen for changes in the source editing mode if the plugin is available.
+      if (sourceEditing) {
+        sourceEditing.on('change:isSourceEditingMode', (evt, name, value) => {
+          button.isEnabled = !value;  // Disable button if in source editing mode.
         });
+      }
+
+      return button;
+    });
+
+  }
+
+  _aidmiJSONImages(content) {
+    // Create a temporary DOM element to parse the HTML string
+    const tempDiv = document.createElement('div');
+    tempDiv.innerHTML = content; // Convert the HTML string to DOM elements
+    // Find all images with the class 'aidmi-dialog-image'
+    let images = tempDiv.querySelectorAll('img, drupal-media');
 
-        // Set focus on the first input for screen readers
-        document.querySelector('input[type="radio"]').focus();
-    }
+    // Initialize an empty array to store the JSON data
+    let imageJsonArray = [];
 
-    _collectSelections(data) {
-        let allSelected = true;
-        const selections = [];
+    // Loop through each image and extract 'data-entity-uuid' and 'src'
+    images.forEach((image) => {
+      let imageObject = {
+        "data-entity-uuid": image.getAttribute('data-entity-uuid'),
+        "type": image.tagName.toLowerCase()
+      };
+      
+      // Push the image object to the array
+      imageJsonArray.push(imageObject);
+    });
     
-        // Loop through the images
-        data.forEach(item => {
-            if (item.images && Array.isArray(item.images)) {
-                item.images.forEach((image) => {
-                    const uuid = image['data-entity-uuid'];
-                    const selectedRadio = document.querySelector(`input[name="aidmi-alt-selection-${uuid}"]:checked`);
-                    
-                    // If no radio button is selected, set `allSelected` to false
-                    if (!selectedRadio) {
-                        allSelected = false;
-                        // Highlight the missing selection group
-                        document.getElementById(`option-group-${uuid}`).classList.add('aidmi-highlight-missing');
-                    } else {
-                        // Get the selected value and corresponding alt text or set as decorative
-                        const altValue = selectedRadio.value;
-                        let altText = '';
-                        if (altValue === 'current') {
-                            altText = document.getElementById(`aidmi-dialog-textarea-oldalt-${uuid}`).value;
-                        } else if (altValue === 'suggested') {
-                            altText = document.getElementById(`aidmi-dialog-textarea-newalt-${uuid}`).value;
-                        }
-                        selections.push({
-                            uuid: uuid,
-                            altText: altValue === 'decorative' ? '' : altText, // Leave alt text empty for decorative images
-                            isDecorative: altValue === 'decorative'
-                        });
-                    }
-                });
-            }
+    // Convert the array to a JSON string for output or further use
+    return imageJsonArray;
+  }
+
+  _aidmiContentAjax(content, imagesJSON) {   
+    const $ = jQuery;
+    return new Promise((resolve, reject) => {
+      $.ajax({
+        url: '/admin/aidmi/describe-content-ajax',
+        method: 'POST',
+        data: {
+          content: content,
+          imagesJSON: JSON.stringify(imagesJSON)
+        },
+        success: function(response) {
+          resolve(response);
+        },
+        error: function(xhr, status, error) {
+          reject(error);
+        }
+      });
+    });
+  }
+
+  _openDialog(editor, data, callback) {
+    let aidmiEditedText;
+    // Create a temporary container to hold the content.
+    const tempElement = document.createElement('div');
+    tempElement.setAttribute('role', 'dialog');
+    tempElement.setAttribute('aria-labelledby', 'aidmi-dialog-title');
+    tempElement.setAttribute('aria-describedby', 'aidmi-dialog-description');
+    tempElement.setAttribute('aria-modal', 'true'); // Ensures screen readers treat the dialog as a modal.
+
+    // Set title text.
+    let tempETitle = 'AIDmi Description';
+    let tempESubTitle = 'Please evaluate and edit the description as needed.';
+
+    // Create dialog content with a textarea for editing.
+    tempElement.innerHTML = `<p id="aidmi-dialog-subtitle" class="aidmi-dialog-subtitle">${Drupal.t(tempESubTitle)}</p>`;
+
+    // Variable to store the number of images
+    let imageCount = 0;
+    data.forEach(item => {
+      if (item.images && Array.isArray(item.images)) {
+        imageCount += item.images.length;
+      }
+    });
+    // Loop through the images
+    data.forEach(item => {
+      // If item has an images array, loop through it
+      if (item.images && Array.isArray(item.images)) {
+        item.images.forEach((image) => {
+          let formImageInnerHTML = '';
+          // Start of image div alt option area.
+          formImageInnerHTML += `<div class="image-option-group" id="option-group-${image['data-entity-uuid']}">`;
+          // Add Image Display.
+          formImageInnerHTML += `
+            <!-- Image Display -->
+            <img class="aidmi-dialog-image" data-entity-uuid="${image['data-entity-uuid']}" src="${image.src}" alt="${Drupal.t(image.before_alt)}" />`;
+          // Add Current Alt Tag Section.
+          let imageOldSelectDisabled = false;
+          let imageLabel = 'Current Alt Tag - Read only';
+          let imageBeforeAlt = image.before_alt;
+          if (!imageBeforeAlt || imageBeforeAlt.length < 6) {
+            // Old alt shouldn't be an allowed option.
+            imageLabel += ' (Option disabled since alt is either blank or too short)';
+            imageOldSelectDisabled = true;
+          }
+          formImageInnerHTML += `
+            <!-- Current Alt Tag Section -->
+            <div>
+              <label for="aidmi-alt-old-${image['data-entity-uuid']}" class="aidmi-dialog-label">
+                <input type="radio" name="aidmi-alt-selection-${image['data-entity-uuid']}" id="aidmi-alt-old-${image['data-entity-uuid']}" value="current" aria-labelledby="label-old-${image['data-entity-uuid']}" ${imageOldSelectDisabled ? 'disabled' : ''} required/>
+                <span id="label-old-${image['data-entity-uuid']}">${Drupal.t(imageLabel)}</span>
+              </label>`; 
+
+          // If radio is disabled, don't show the alt textarea.
+          if (!imageOldSelectDisabled) {
+            formImageInnerHTML += `
+                <textarea id="aidmi-dialog-textarea-oldalt-${image['data-entity-uuid']}" class="aidmi-dialog-textarea" rows="3" aria-labelledby="label-old-${image['data-entity-uuid']}" readonly="readonly">${Drupal.t(image.before_alt)}</textarea>`;
+          }
+          
+          formImageInnerHTML += `
+            </div>`;   
+          
+          // Add Suggested Alt Tag Section.
+          formImageInnerHTML += `
+            <!-- Suggested Alt Tag Section -->
+            <div>
+              <label for="aidmi-alt-new-${image['data-entity-uuid']}" class="aidmi-dialog-label">
+                <input type="radio" name="aidmi-alt-selection-${image['data-entity-uuid']}" id="aidmi-alt-new-${image['data-entity-uuid']}" value="suggested" aria-labelledby="label-new-${image['data-entity-uuid']}" required>
+                <span id="label-new-${image['data-entity-uuid']}">${Drupal.t('Suggested Alt Tag - Review and modify as required')}</span>
+              </label>
+              <textarea id="aidmi-dialog-textarea-newalt-${image['data-entity-uuid']}" class="aidmi-dialog-textarea" rows="3" aria-labelledby="label-new-${image['data-entity-uuid']}">${Drupal.t(image.recommendation)}</textarea>
+            </div>`;
+          // Add Set as Decorative Image.
+          formImageInnerHTML += `
+            <!-- Set as Decorative Image -->
+            <div>
+              <label for="aidmi-alt-decorative-${image['data-entity-uuid']}" class="aidmi-dialog-label">
+                <input type="radio" name="aidmi-alt-selection-${image['data-entity-uuid']}" id="aidmi-alt-decorative-${image['data-entity-uuid']}" value="decorative" aria-labelledby="label-decorative-${image['data-entity-uuid']}" required>
+                <span id="label-decorative-${image['data-entity-uuid']}">${Drupal.t('Set as Decorative Image')}</span>
+              </label>
+            </div>`;
+          // End of image div alt option area.
+          formImageInnerHTML += `</div><hr/>`;
+          
+          // Insert it.
+          tempElement.innerHTML += formImageInnerHTML;
         });
-    
-        return allSelected ? selections : null;
-    }
-
-    // Function to modify the images in the CKEditor content based on the selected options
-    _modifyImagesInContent(editor, selections) {
-        // Get the current content of the editor
-        let content = editor.getData();
-
-        // Create a temporary DOM element to manipulate the HTML content
-        const tempDiv = document.createElement('div');
-        tempDiv.innerHTML = content; // Convert the HTML string to DOM elements
-
-        // Loop through the selections and modify the corresponding images in the content
-        selections.forEach(selection => {
-            // Find the image element by its data-entity-uuid attribute
-            const imageElement = tempDiv.querySelector(`[data-entity-uuid="${selection.uuid}"]`);
-            
-            if (imageElement) {
-                // Update the alt attribute or set as decorative based on the selection
-                if (selection.isDecorative) {
-                    imageElement.setAttribute('alt', ''); // Set alt attribute to empty for decorative images
-                    imageElement.setAttribute('role', 'presentation'); // Add role="presentation" to decorative images
-                } else {
-                    imageElement.setAttribute('alt', selection.altText); // Update the alt attribute
-                    imageElement.removeAttribute('role'); // Remove role attribute if it's not a decorative image
-                }
-                
+      }            
+    });
+
+    // Use the Drupal off-canvas dialog to show the content.
+    const options = {
+      dialogClass: 'aidmi-dialog',
+      title: tempETitle,
+      resizable: true,
+      width: '700px',
+      buttons: [
+        {
+          text: Drupal.t('Insert Text'),
+          class: 'aidmi-insert-button', // Add a class to the insert button for reference
+          click: () => {
+            // Validate all selections before inserting text
+            const selections = this._collectSelections(data);
+            if (selections) {
+              // Modify the images in the editor content based on the selections
+              this._modifyImagesInContent(editor, selections);
+              dialogInstance.close();
             } else {
-                console.warn(`Image with UUID ${selection.uuid} not found in content.`);
+              // Show a message if validation fails
+              alert(Drupal.t('Please select an option for each image before inserting.'));
             }
+          }
+        },
+        {
+          text: Drupal.t('Cancel'),
+          click: function () {
+            // Close the dialog.
+            dialogInstance.close();
+          }
+        }
+      ]
+    };
+
+    // Open the dialog using Drupal's dialog API.
+    const dialogInstance = Drupal.dialog(tempElement, options);
+    dialogInstance.showModal();
+
+    // Add event listeners to all radio buttons to validate the selection and remove highlights
+    document.querySelectorAll('input[type="radio"]').forEach(radio => {
+      radio.addEventListener('change', (event) => {
+        const groupId = event.target.name.replace('aidmi-alt-selection-', 'option-group-');
+        // Remove the highlight class when a selection is made
+        document.getElementById(groupId).classList.remove('aidmi-highlight-missing');
+      });
+    });
+
+    // Set focus on the first input for screen readers
+    document.querySelector('input[type="radio"]').focus();
+  }
+
+  _collectSelections(data) {
+    let allSelected = true;
+    const selections = [];
+  
+    // Loop through the images
+    data.forEach(item => {
+      if (item.images && Array.isArray(item.images)) {
+        item.images.forEach((image) => {
+          const uuid = image['data-entity-uuid'];
+          const selectedRadio = document.querySelector(`input[name="aidmi-alt-selection-${uuid}"]:checked`);
+          
+          // If no radio button is selected, set `allSelected` to false
+          if (!selectedRadio) {
+            allSelected = false;
+            // Highlight the missing selection group
+            document.getElementById(`option-group-${uuid}`).classList.add('aidmi-highlight-missing');
+          } else {
+            // Get the selected value and corresponding alt text or set as decorative
+            const altValue = selectedRadio.value;
+            let altText = '';
+            if (altValue === 'current') {
+              altText = document.getElementById(`aidmi-dialog-textarea-oldalt-${uuid}`).value;
+            } else if (altValue === 'suggested') {
+              altText = document.getElementById(`aidmi-dialog-textarea-newalt-${uuid}`).value;
+            }
+            selections.push({
+              uuid: uuid,
+              altText: altValue === 'decorative' ? '' : altText, // Leave alt text empty for decorative images
+              isDecorative: altValue === 'decorative'
+            });
+          }
         });
+      }
+    });
+  
+    return allSelected ? selections : null;
+  }
+
+  // Function to modify the images in the CKEditor content based on the selected options
+  _modifyImagesInContent(editor, selections) {
+    // Get the current content of the editor
+    let content = editor.getData();
+
+    // Create a temporary DOM element to manipulate the HTML content
+    const tempDiv = document.createElement('div');
+    tempDiv.innerHTML = content; // Convert the HTML string to DOM elements
+
+    // Loop through the selections and modify the corresponding images in the content
+    selections.forEach(selection => {
+      // Find the image element by its data-entity-uuid attribute
+      const imageElement = tempDiv.querySelector(`[data-entity-uuid="${selection.uuid}"]`);
+      
+      if (imageElement) {
+        // Update the alt attribute or set as decorative based on the selection
+        if (selection.isDecorative) {
+          imageElement.setAttribute('alt', ''); // Set alt attribute to empty for decorative images
+          imageElement.setAttribute('role', 'presentation'); // Add role="presentation" to decorative images
+        } else {
+          imageElement.setAttribute('alt', selection.altText); // Update the alt attribute
+          imageElement.removeAttribute('role'); // Remove role attribute if it's not a decorative image
+        }
+        
+      } else {
+        console.warn(`Image with UUID ${selection.uuid} not found in content.`);
+      }
+    });
 
-        // Set the modified content back to the editor
-        editor.setData(tempDiv.innerHTML);
+    // Set the modified content back to the editor
+    editor.setData(tempDiv.innerHTML);
 
-        // Optional: Trigger the change event to update the editor state
-        editor.editing.view.document.fire('change:data');
-    }   
+    // Optional: Trigger the change event to update the editor state
+    editor.editing.view.document.fire('change:data');
+  }   
 
 }
diff --git a/src/Controller/AidmiController.php b/src/Controller/AidmiController.php
index 8336de1932bd5ec768a981e1b50de1511e8796bb..e10e7a8b0bfa69ff6dbb18623a15ba5360e87f81 100644
--- a/src/Controller/AidmiController.php
+++ b/src/Controller/AidmiController.php
@@ -2,13 +2,13 @@
 
 namespace Drupal\aidmi\Controller;
 
-use Symfony\Component\HttpFoundation\Response;
-use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\aidmi\Service\GeminiAiService;
-use Drupal\Core\Render\Element;
-use Symfony\Component\HttpFoundation\JsonResponse;
-use Drupal\file\Entity\File;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\Response;
 
+/**
+ *
+ */
 class AidmiController {
   protected $geminiAiService;
 
@@ -16,56 +16,74 @@ class AidmiController {
     $this->geminiAiService = $geminiAiService;
   }
 
+  /**
+   *
+   */
   public static function create(ContainerInterface $container): self {
     return new static(
       $container->get('aidmi.ai_service')
     );
   }
 
+  /**
+   *
+   */
   public function analyzeImage(int $fid): Response {
     // Set the file ID in drupalSettings so it can be accessed in JavaScript.
     $build = [];
     $build['#attached']['drupalSettings']['aidmi'] = [
       'imageFid' => $fid,
     ];
-  
+
     $description = $this->geminiAiService->analyzeImage($fid);
-  
+
     // Return a response for the page.
     return new Response($description);
   }
 
+  /**
+   *
+   */
   public function analyzeImageAjax(string $uuid): Response {
     $fid = $this->getFileIdByUuid($uuid);
     if ($fid) {
       $description = $this->geminiAiService->analyzeImage($fid);
       return new Response($description);
     }
-    return null;
+    return NULL;
   }
 
+  /**
+   *
+   */
   public function analyzeContentAjax(): Response {
     // Get the raw POST data from the request.
     $content = \Drupal::request()->request->get('content');
     $imagesJSON = \Drupal::request()->request->get('imagesJSON');
-    $description = null;
-    
+    $description = NULL;
+
     if (!empty($content)) {
       $description = $this->geminiAiService->analyzeContent($content, $imagesJSON);
-    }    
+    }
 
     return new Response($description);
   }
-  
+
+  /**
+   *
+   */
   public function getFileIdByUuid(string $uuid) {
     // Query for the file entity using the UUID.
     $file = \Drupal::entityTypeManager()->getStorage('file')->loadByProperties(['uuid' => $uuid]);
 
     if ($file) {
-      $file = reset($file);  // Get the first result.
+      // Get the first result.
+      $file = reset($file);
       return $file->id();
-    } else {
-      return null;
+    }
+    else {
+      return NULL;
     }
   }
+
 }
diff --git a/src/Form/AidmiSettingsForm.php b/src/Form/AidmiSettingsForm.php
index 8129ecf16883b6be96e4dee967a1cc96cb14ad88..bdf8669d5f7e710e027fb98b8759aed9f75eee33 100644
--- a/src/Form/AidmiSettingsForm.php
+++ b/src/Form/AidmiSettingsForm.php
@@ -1,4 +1,5 @@
 <?php
+
 namespace Drupal\aidmi\Form;
 
 use Drupal\Core\Form\ConfigFormBase;
@@ -40,21 +41,24 @@ class AidmiSettingsForm extends ConfigFormBase {
     $file_status_message = '';
 
     $site_root = \Drupal::root();
-    
+
     // Check if the file input method is selected and if the file exists.
     if ($api_input_method === 'file_path' && !empty($api_key_file_path)) {
-      $full_file_path = $site_root . '/' . ltrim($api_key_file_path, '/'); // Ensure no double slashes.
+      // Ensure no double slashes.
+      $full_file_path = $site_root . '/' . ltrim($api_key_file_path, '/');
       if (file_exists($full_file_path)) {
         $file_status_message = $this->t('File found: @path', ['@path' => $full_file_path]);
-        \Drupal::messenger()->addStatus($file_status_message); // Add as a status message.
+        // Add as a status message.
+        \Drupal::messenger()->addStatus($file_status_message);
       }
       else {
         $file_status_message = $this->t('File not found at the provided path: @path', ['@path' => $full_file_path]);
-        \Drupal::messenger()->addError($file_status_message); // Add as an error message.
+        // Add as an error message.
+        \Drupal::messenger()->addError($file_status_message);
       }
     }
 
-    // Radio buttons for API selection
+    // Radio buttons for API selection.
     $form['selected_api'] = [
       '#type' => 'radios',
       '#title' => $this->t('Select API'),
@@ -65,7 +69,7 @@ class AidmiSettingsForm extends ConfigFormBase {
       '#description' => $this->t('Select which API to use for processing.'),
       '#required' => TRUE,
     ];
-    
+
     // Add a radio button to select the input method.
     $form['api_input_method'] = [
       '#type' => 'radios',
@@ -92,9 +96,9 @@ class AidmiSettingsForm extends ConfigFormBase {
         'id' => 'api-key-field',
       ],
     ];
-    
+
     $recommended_path = $site_root . '/../api_keys/aidmi.key';
-    
+
     $form['api_key_file_path'] = [
       '#type' => 'textfield',
       '#title' => $this->t('API Key File Path'),
@@ -118,7 +122,7 @@ class AidmiSettingsForm extends ConfigFormBase {
       ],
     ];
 
-    // Field for the API instructions
+    // Field for the API instructions.
     $form['api_instructions'] = [
       '#type' => 'textarea',
       '#title' => $this->t('API Instructions'),
@@ -135,28 +139,32 @@ class AidmiSettingsForm extends ConfigFormBase {
    */
   public function submitForm(array &$form, FormStateInterface $form_state) {
 
-        // Prepare the config object for saving.
-        $config = $this->configFactory()->getEditable('aidmi.settings');
-
-        // Get the selected API input method.
-        $api_input_method = $config->get('api_input_method');
-
-        if ($api_input_method === 'file_path') {
-          // Clear the old API key if the file path is chosen.
-          $config->set('api_key', '');
-        } else {
-          // Save the entered API key if the API key method is chosen.
-          $config->set('api_key', $form_state->getValue('api_key'));
-        }
-    
-        // Save the API input method and the file path (if applicable).
-        $config->set('api_input_method', $api_input_method)
-          ->set('api_input_method', $form_state->getValue('api_input_method'))  // Save selected API Key method      
-          ->set('selected_api', $form_state->getValue('selected_api'))  // Save selected API
-          ->set('api_key_file_path', $form_state->getValue('api_key_file_path'))
-          ->set('api_instructions', $form_state->getValue('api_instructions'))
-          ->save();
+    // Prepare the config object for saving.
+    $config = $this->configFactory()->getEditable('aidmi.settings');
+
+    // Get the selected API input method.
+    $api_input_method = $config->get('api_input_method');
+
+    if ($api_input_method === 'file_path') {
+      // Clear the old API key if the file path is chosen.
+      $config->set('api_key', '');
+    }
+    else {
+      // Save the entered API key if the API key method is chosen.
+      $config->set('api_key', $form_state->getValue('api_key'));
+    }
+
+    // Save the API input method and the file path (if applicable).
+    $config->set('api_input_method', $api_input_method)
+    // Save selected API Key method.
+      ->set('api_input_method', $form_state->getValue('api_input_method'))
+    // Save selected API.
+      ->set('selected_api', $form_state->getValue('selected_api'))
+      ->set('api_key_file_path', $form_state->getValue('api_key_file_path'))
+      ->set('api_instructions', $form_state->getValue('api_instructions'))
+      ->save();
 
     parent::submitForm($form, $form_state);
   }
+
 }
diff --git a/src/Plugin/CKEditor5Plugin/aidmi.php b/src/Plugin/CKEditor5Plugin/aidmi.php
deleted file mode 100644
index 96677f1bc1892b347c08a077f359f182f8c5ddd0..0000000000000000000000000000000000000000
--- a/src/Plugin/CKEditor5Plugin/aidmi.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-declare(strict_types = 1);
-
-namespace Drupal\aidmi\Plugin\CKEditor5Plugin;
-
-use Drupal\ckeditor5\Plugin\CKEditor5PluginDefault;
-use Drupal\Core\Url;
-use Drupal\editor\EditorInterface;
-
-/**
- * Plugin class to add dialog url for embedded content.
- */
-class aidmi extends CKEditor5PluginDefault {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getDynamicPluginConfig(array $static_plugin_config, EditorInterface $editor): array {
-    $aidmi_dialog_url = Url::fromRoute('ckeditor5_aidmi.dialog')
-      ->toString(TRUE)
-      ->getGeneratedUrl();
-    $static_plugin_config['aidmi']['dialogURL'] = $aidmi_dialog_url;
-    $aidmi_preview_url = Url::fromRoute('ckeditor5_aidmi.preview', [
-      'editor' => $editor->id(),
-    ])
-      ->toString(TRUE)
-      ->getGeneratedUrl();
-    // $static_plugin_config['aidmi']['previewURL'] = $aidmi_preview_url;
-    return $static_plugin_config;
-  }
-
-}
diff --git a/src/Service/GeminiAiService.php b/src/Service/GeminiAiService.php
index f297e0bec21ac6fbb4633a9c677efc377ad3cccb..8387eb2c572df45426384dbf9d626e54a486eea9 100644
--- a/src/Service/GeminiAiService.php
+++ b/src/Service/GeminiAiService.php
@@ -2,25 +2,32 @@
 
 namespace Drupal\aidmi\Service;
 
-use Drupal\file\Entity\File;  // Correct namespace for Drupal File Entity
 use Drupal\Core\Config\ConfigFactoryInterface;
-use Drupal\Component\Utility\Html;
-use Drupal\media\Entity\Media;
+use Drupal\file\Entity\File;
+// Correct namespace for Drupal File Entity.
+use Drupal\file\FileInterface;
 
+/**
+ *
+ */
 class GeminiAiService {
-  // Gemini Base URL and Header for API Key.
+  /**
+   * Gemini Base URL and Header for API Key.
+   */
   private string $baseUrl = 'https://generativelanguage.googleapis.com';
   private string $apiKeyHeader = 'x-goog-api-key';
-  
-  // Gemini Models.
-  private string $GeminiPro = 'models/gemini-pro';
-  private string $GeminiPro10 = 'models/gemini-1.0-pro';
-  private string $GeminiPro10Latest = 'models/gemini-1.0-pro-latest';
-  private string $GeminiPro15 = 'models/gemini-1.5-pro';
-  private string $GeminiPro15Flash = 'models/gemini-1.5-flash';
-  private string $GeminiProVision = 'models/gemini-pro-vision';
-  private string $Embedding = 'models/embedding-001';
-  private string $AQA = 'models/aqa';
+
+  /**
+   * Gemini Models.
+   */
+  private string $geminiPro = 'models/gemini-pro';
+  private string $geminiPro10 = 'models/gemini-1.0-pro';
+  private string $geminiPro10Latest = 'models/gemini-1.0-pro-latest';
+  private string $geminiPro15 = 'models/gemini-1.5-pro';
+  private string $geminiPro15Flash = 'models/gemini-1.5-flash';
+  private string $geminiProVision = 'models/gemini-pro-vision';
+  private string $embedding = 'models/embedding-001';
+  private string $aqa = 'models/aqa';
 
   /**
    * The configuration factory service.
@@ -49,7 +56,6 @@ class GeminiAiService {
    * @var \Drupal\aidmi\Controller\AidmiController
    */
   protected $aidmiController;
-  
 
   public function __construct(ConfigFactoryInterface $configFactory) {
     $this->configFactory = $configFactory;
@@ -65,98 +71,115 @@ class GeminiAiService {
     if ($apiInputMethod === 'file_path') {
       // Get the API key file path from the configuration.
       $apiKeyFilePath = $config->get('api_key_file_path');
-      $siteRoot = \Drupal::root(); // Get the site root.
-      $fullFilePath = $siteRoot . '/' . ltrim($apiKeyFilePath, '/'); // Full file path.
+      // Get the site root.
+      $siteRoot = \Drupal::root();
+      // Full file path.
+      $fullFilePath = $siteRoot . '/' . ltrim($apiKeyFilePath, '/');
       // Check if the file exists and is readable.
       if (file_exists($fullFilePath) && is_readable($fullFilePath)) {
         // Read the API key from the file.
         $apiKey = trim(file_get_contents($fullFilePath));
-      } else {
-        // Log an error and default the API key to an empty string or a default value.
+      }
+      else {
+        // Log an error and default the API key.
         \Drupal::logger('aidmi')->error('API key file not found or not readable at @path', ['@path' => $fullFilePath]);
-        $apiKey = '0'; // Fallback if file is not found or readable.
+        // Fallback if file is not found or readable.
+        $apiKey = '0';
       }
-    } else {
-      // Get the API key from the configuration if the input method is 'api_key'.
+    }
+    else {
+      // Get the API key from the configuration.
       $apiKey = $config->get('api_key');
-      
+
       // Default to '0' if the API key is empty.
       if (empty($apiKey)) {
         $apiKey = '0';
       }
     }
-    
+
     $this->apiKey = $apiKey;
     $this->apiInstructions = $config->get('api_instructions');
   }
 
+  /**
+   *
+   */
   public function analyzeImage(int $fid): string {
     try {
       $file = File::load($fid);
       if (!$file) {
         throw new \Exception(t('File not found.'));
       }
-  
+
       $imagePath = $file->getFileUri();
       $imageContent = file_get_contents($imagePath);
       if (!$imageContent) {
         throw new \Exception(t('Unable to open image file.'));
       }
-  
+
       $output = $this->geminiReviewImage($imagePath);
 
       return $output;
-    } catch (\Exception $e) {
-        return 'Error: ' . $e->getMessage();
+    }
+    catch (\Exception $e) {
+      return 'Error: ' . $e->getMessage();
     }
   }
 
+  /**
+   *
+   */
   public function analyzeContent(string $content, string $imagesJSON): string {
-    try {      
+    try {
       $output = $this->geminiReviewContent($content, $imagesJSON);
       $output = str_replace("```json", "", $output);
       $output = str_replace("```", "", $output);
-  
+
       return $output;
-    } catch (\Exception $e) {
+    }
+    catch (\Exception $e) {
       return 'Error: ' . $e->getMessage();
     }
   }
-  
+
+  /**
+   *
+   */
   public function getFileIdByUuid(string $uuid, string $type) {
-    $file = null;
-  
+    $file = NULL;
+
     // If type is drupal-media, load media entity first.
     if ($type == 'drupal-media') {
       $media = $this->loadMediaByUuid($uuid);
       if ($media && $media->bundle() === 'image') {
-        // Check if the media entity has the 'field_media_image' field and it's not empty.
+        // Check if the media entity has the field.
         if ($media->hasField('field_media_image') && !$media->get('field_media_image')->isEmpty()) {
           $file_id = $media->get('field_media_image')->target_id;
           // Load the file entity using the file ID.
           $file = File::load($file_id);
         }
       }
-    } else {
+    }
+    else {
       // If type is not drupal-media, directly get file entity by UUID.
       $files = \Drupal::entityTypeManager()->getStorage('file')->loadByProperties(['uuid' => $uuid]);
       if (!empty($files)) {
         $file = reset($files);
       }
     }
-  
+
     // Check if the file is loaded and valid.
-    if ($file instanceof \Drupal\file\FileInterface) {
+    if ($file instanceof FileInterface) {
       return $file;
     }
     elseif ($media && $media->bundle() != 'image') {
-      return null;
+      return NULL;
     }
     else {
       throw new \Exception(t('File not found for UUID: @uuid', ['@uuid' => $uuid]));
     }
   }
-  
+
   /**
    * Load a media entity by its UUID.
    *
@@ -166,26 +189,28 @@ class GeminiAiService {
    * @return \Drupal\media\MediaInterface|null
    *   The media entity object if found, otherwise null.
    */
-  function loadMediaByUuid($uuid) {
+  public function loadMediaByUuid($uuid) {
     // Load the media entity using the UUID.
     $media_entities = \Drupal::entityTypeManager()
       ->getStorage('media')
       ->loadByProperties(['uuid' => $uuid]);
-  
+
     // Check if any media entities are returned.
     if (!empty($media_entities)) {
       // Get the first media entity from the array.
       return reset($media_entities);
     }
-  
-    return null;
+
+    return NULL;
   }
 
-  function geminiReviewImage(string $imagePath):string {    
+  /**
+   *
+   */
+  public function geminiReviewImage(string $imagePath):string {
     // Keeping all models in here for now.
-
-    // Connect
-    $ch = curl_init($this->baseUrl . "/v1/" . $this->GeminiPro15Flash . ":streamGenerateContent");
+    // Connect.
+    $ch = curl_init($this->baseUrl . "/v1/" . $this->geminiPro15Flash . ":streamGenerateContent");
     // Setup request to send json via POST.
     // The text prompt you want to send.
     $prompt = $this->apiInstructions;
@@ -193,43 +218,42 @@ class GeminiAiService {
     $imageData = base64_encode(file_get_contents($imagePath));
     // Prepare the data payload.
     $data = [
-        'contents' => [
-          'parts' => [
+      'contents' => [
+        'parts' => [
               [
-                  'text' => $prompt,
+                'text' => $prompt,
               ],
               [
                 'inlineData' => [
-                    'mimeType' => 'image/jpeg',
-                    'data' => $imageData,
-                ]            
+                  'mimeType' => 'image/jpeg',
+                  'data' => $imageData,
+                ],
               ],
-          ],
-        ]
+        ],
+      ],
     ];
-    
+
     curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
-    curl_setopt($ch, CURLOPT_HTTPHEADER, array($this->apiKeyHeader .': '. $this->apiKey, 'Content-Type:application/json'));
+    curl_setopt($ch, CURLOPT_HTTPHEADER, [$this->apiKeyHeader . ': ' . $this->apiKey, 'Content-Type:application/json']);
     // Return response instead of printing.
-    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
+    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
     // Send request.
     $result = curl_exec($ch);
     curl_close($ch);
     // Decode and handle the response.
-    $resultData = json_decode($result, true);
-    //return $result;
-    
-    $fullDescription = null;
+    $resultData = json_decode($result, TRUE);
+    // Return $result;.
+    $fullDescription = NULL;
 
     // Iterate through each candidate in the response data.
     foreach ($resultData as $entry) {
       if (isset($entry['candidates'][0]['content']['parts'])) {
-          // Concatenate all the text parts together.
-          foreach ($entry['candidates'][0]['content']['parts'] as $part) {
-              if (isset($part['text'])) {
-                $fullDescription .= $part['text'];
-              }
+        // Concatenate all the text parts together.
+        foreach ($entry['candidates'][0]['content']['parts'] as $part) {
+          if (isset($part['text'])) {
+            $fullDescription .= $part['text'];
           }
+        }
       }
     }
 
@@ -237,90 +261,90 @@ class GeminiAiService {
     if (isset($fullDescription)) {
       return $fullDescription;
     }
-    else {      
+    else {
       return '**Error**';
     }
   }
 
-  
-  function geminiReviewContent(string $content, string $imagesJSON):string {        
-    // Decode JSON string into PHP array
-    $jsonArray = json_decode($imagesJSON, true);
+  /**
+   *
+   */
+  public function geminiReviewContent(string $content, string $imagesJSON):string {
+    // Decode JSON string into PHP array.
+    $jsonArray = json_decode($imagesJSON, TRUE);
 
-    // Connect
-    $ch = curl_init($this->baseUrl . "/v1/" . $this->GeminiPro15Flash . ":streamGenerateContent");
+    // Connect.
+    $ch = curl_init($this->baseUrl . "/v1/" . $this->geminiPro15Flash . ":streamGenerateContent");
     // Setup request to send json via POST.
     // The text prompt you want to send.
     $prompt = $this->apiInstructions;
     $prompt = 'Response can only be in JSON. Do not provide null value if something is empty, just keep it "" blank. Exact JSON output example: [{"images": [{"data-entity-uuid": "", "src": "", "before_alt": "", "recommendation": "", "decorative_image" = ""}]}, {"message": "error or other message if needed"}]. Review this content and describe the image. Actual images from the content are attached and referenced by data-entity-uuid. Provide a json output with each image by data-entity-uuid, image src, the before alt text if available, and your recommendation. If there is a problem, respond with only an error JSON. Provide a true or false for decorative image where just an alt tag alone is decorative, but alt="" is false. ' . $prompt;
-        
+
     $generateContent = [];
 
     $generateContent[] = ['text' => $prompt];
 
     foreach ($jsonArray as $item) {
-      $imagePath = null;
-      $imageContent = null;
+      $imagePath = NULL;
+      $imageContent = NULL;
 
       // Get file entity by UUID.
       $file = $this->getFileIdByUuid($item['data-entity-uuid'], $item['type']);
-      
-      if ($file instanceof \Drupal\file\FileInterface) {
+
+      if ($file instanceof FileInterface) {
         $imagePath = \Drupal::service('file_system')->realpath($file->getFileUri());
         // Use the file_url_generator service to generate the URL.
         $url = \Drupal::service('file_url_generator')->generateAbsoluteString($file->getFileUri());
 
-        if (file_exists($imagePath)) {  // Check if file path is valid.
+        // Check if file path is valid.
+        if (file_exists($imagePath)) {
           $imageContent = file_get_contents($imagePath);
         }
       }
-      
+
       // If there is an image, do it.
-      if ($imageContent) {    
+      if ($imageContent) {
         // Attach images for Gemini AI review.
-        
-        $generateContent[] = ['text' => "data-entity-uuid: " . $item['data-entity-uuid'] .", src: ". $url];
+        $generateContent[] = ['text' => "data-entity-uuid: " . $item['data-entity-uuid'] . ", src: " . $url];
         $generateContent[] = [
           'inlineData' => [
-              'mimeType' => 'image/jpeg',
-              'data' => base64_encode($imageContent),
-          ]            
-          ]; 
+            'mimeType' => 'image/jpeg',
+            'data' => base64_encode($imageContent),
+          ],
+        ];
       }
     }
-    
-    
+
     // Read the image file and encode it in base64.
     $imageData = base64_encode(file_get_contents($imagePath));
     // Prepare the data payload.
     $data = [
-        'contents' => [
-          'parts' => $generateContent,
-        ]
+      'contents' => [
+        'parts' => $generateContent,
+      ],
     ];
-    
+
     curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
-    curl_setopt($ch, CURLOPT_HTTPHEADER, array($this->apiKeyHeader .': '. $this->apiKey, 'Content-Type:application/json'));
+    curl_setopt($ch, CURLOPT_HTTPHEADER, [$this->apiKeyHeader . ': ' . $this->apiKey, 'Content-Type:application/json']);
     // Return response instead of printing.
-    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
+    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
     // Send request.
     $result = curl_exec($ch);
     curl_close($ch);
     // Decode and handle the response.
-    $resultData = json_decode($result, true);
-    //return $result;
-    
-    $fullDescription = null;
+    $resultData = json_decode($result, TRUE);
+    // Return $result;.
+    $fullDescription = NULL;
 
     // Iterate through each candidate in the response data.
     foreach ($resultData as $entry) {
       if (isset($entry['candidates'][0]['content']['parts'])) {
-          // Concatenate all the text parts together.
-          foreach ($entry['candidates'][0]['content']['parts'] as $part) {
-              if (isset($part['text'])) {
-                $fullDescription .= $part['text'];
-              }
+        // Concatenate all the text parts together.
+        foreach ($entry['candidates'][0]['content']['parts'] as $part) {
+          if (isset($part['text'])) {
+            $fullDescription .= $part['text'];
           }
+        }
       }
     }
 
@@ -328,9 +352,9 @@ class GeminiAiService {
     if (isset($fullDescription)) {
       return $fullDescription;
     }
-    else {      
+    else {
       return '**Error**';
     }
   }
-  
+
 }