From dc992d65395d4105e151c0c828e3c20b878c1faf Mon Sep 17 00:00:00 2001
From: Snater <git@snater.com>
Date: Tue, 2 Apr 2024 12:46:18 +0200
Subject: [PATCH] Issue #3314446: Fixed adding tags and attributes to text
 format

---
 insert.module                 | 16 +++++++++++-----
 src/Utility/InsertUtility.php | 25 ++++++++++++++++++-------
 2 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/insert.module b/insert.module
index 162f4a1..abc2c0b 100644
--- a/insert.module
+++ b/insert.module
@@ -103,7 +103,7 @@ function insert_form_alter(array &$form, FormStateInterface $form_state, $form_i
           = '_insert_allowed_html_validate';
       }
       if (isset($form['editor']['settings']['subform']['plugins']['ckeditor5_sourceEditing'])) {
-        $form['editor']['settings']['plugins']['ckeditor5_sourceEditing']['allowed_tags']['#element_validate'][]
+        $form['editor']['settings']['subform']['plugins']['ckeditor5_sourceEditing']['allowed_tags']['#element_validate'][]
           = '_insert_allowed_html_validate';
       }
     }
@@ -805,6 +805,9 @@ function insert_editor_js_settings_alter(array &$settings) {
  * @param \Drupal\Core\Form\FormStateInterface $form_state
  */
 function _insert_allowed_html_validate(array $element, FormStateInterface &$form_state) {
+  $imagePluginActive
+    = $element['#groups']['editor][settings][plugins][ckeditor5_image']['#group_exists'];
+
   $tags = [
     'img' => NULL,
     'a' => NULL,
@@ -818,10 +821,6 @@ function _insert_allowed_html_validate(array $element, FormStateInterface &$form
       'class' => NULL,
       'data-insert-attach' => NULL,
       'data-insert-type' => NULL,
-      'src' => NULL,
-      'width' => NULL,
-      'height' => NULL,
-      'alt' => NULL,
       'title' => NULL,
     ],
     'a' => [
@@ -857,6 +856,13 @@ function _insert_allowed_html_validate(array $element, FormStateInterface &$form
     ],
   ];
 
+  if (!$imagePluginActive) {
+    $attributes['img']['src'] = NULL;
+    $attributes['img']['alt'] = NULL;
+    $attributes['img']['width'] = NULL;
+    $attributes['img']['height'] = NULL;
+  }
+
   $additional = \Drupal::moduleHandler()->invokeAll('insert_allowed_html');
 
   if (isset($element['#value'])) {
diff --git a/src/Utility/InsertUtility.php b/src/Utility/InsertUtility.php
index ccecb88..b6bc6ee 100644
--- a/src/Utility/InsertUtility.php
+++ b/src/Utility/InsertUtility.php
@@ -6,6 +6,9 @@ use Drupal\Component\Utility\Html;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\file\FileInterface;
 use Drupal\image\Entity\ImageStyle;
+use Masterminds\HTML5\Parser\DOMTreeBuilder;
+use Masterminds\HTML5\Parser\Scanner;
+use Masterminds\HTML5\Parser\Tokenizer;
 
 /**
  *
@@ -196,18 +199,26 @@ class InsertUtility {
    *
    * @return string
    */
-  public static function addAllowedHtml($value, array $tags, array $attributes) {
-    // See \Drupal\filter\Plugin\Filter\FilterHtml::prepareAttributeValues.
+  public static function addAllowedHtml(string $value, array $tags, array $attributes) {
+    // See \Drupal\filter\Plugin\Filter\FilterHtml::getHTMLRestrictions.
     $html = str_replace('>', ' />', $value);
     $star_protector = '__zqh6vxfbk3cg__';
     $html = str_replace('*', $star_protector, $html);
-    $body_child_nodes = Html::load($html)->getElementsByTagName('body')->item(0)->childNodes;
 
-    // Detect which tags an attributes are allowed already.
-    foreach ($body_child_nodes as $node) {
-      if ($node->nodeType !== XML_ELEMENT_NODE) {
-        continue;
+    $events = new DOMTreeBuilder(FALSE, ['disable_html_ns' => TRUE]);
+    $scanner = new Scanner('<body>' . $html);
+    $parser = new class($scanner, $events) extends Tokenizer {
+      public function setTextMode($textmode, $untilTag = NULL) {
+        // Do nothing, we never enter text mode.
       }
+    };
+    $parser->parse();
+
+    $dom = $events->document();
+    $xpath = new \DOMXPath($dom);
+
+    // Detect which tags an attributes are allowed already.
+    foreach ($xpath->query('//body//*') as $node) {
       $tag = $node->tagName;
 
       if (array_key_exists($tag, $tags)) {
-- 
GitLab