Move the mayContainOtherContent check in separate function
authorCyperghost <olaf_schmitz_1@t-online.de>
Wed, 17 Jan 2024 13:51:06 +0000 (14:51 +0100)
committerOlaf Braun <info@braun-development.de>
Thu, 7 Mar 2024 15:36:44 +0000 (16:36 +0100)
Simplify to find the next/previous br

wcfsetup/install/files/lib/system/html/input/node/HtmlInputNodeProcessor.class.php
wcfsetup/install/files/lib/system/html/node/HtmlNodePlainLink.class.php

index c7375f885265691ef0f23d8275cf2891e4650b9a..ad98ebafd759708e00f2ec5d713051a18cbfbfcc 100644 (file)
@@ -779,39 +779,16 @@ class HtmlInputNodeProcessor extends AbstractHtmlNodeProcessor
                 $parent = $parent->parentNode;
             }
             $mayContainOtherContent = false;
+            $linebreaks = 0;
 
             if ($parent->nodeName === 'p' && $parent->textContent === $link->textContent) {
                 // The line may contain nothing but the link, exceptions include basic formatting
                 // and up to a single `<br>` element.
-                $linebreaks = 0;
                 /** @var \DOMElement $element */
                 foreach ($parent->getElementsByTagName('*') as $element) {
-                    switch ($element->nodeName) {
-                        case 'br':
-                            $linebreaks++;
-                            break;
-
-                        case 'span':
-                            if ($element->getAttribute('class')) {
-                                $mayContainOtherContent = true;
-                                break 2;
-                            }
-
-                            // `<span>` is used to hold text formatting.
-                            break;
-
-                        case 'a':
-                        case 'b':
-                        case 'em':
-                        case 'i':
-                        case 'strong':
-                        case 'u':
-                            // These elements are perfectly fine.
-                            break;
-
-                        default:
-                            $mayContainOtherContent = true;
-                            break 2;
+                    if ($this->mayContainOtherContent($element, $linebreaks)) {
+                        $mayContainOtherContent = true;
+                        break;
                     }
                 }
 
@@ -823,29 +800,9 @@ class HtmlInputNodeProcessor extends AbstractHtmlNodeProcessor
                 $parentLinkElement = $link;
                 while ($parentLinkElement->parentElement !== $parent) {
                     $parentLinkElement = $parentLinkElement->parentElement;
-                    switch ($parentLinkElement->nodeName) {
-                        case 'span':
-                            if ($parentLinkElement->getAttribute('class')) {
-                                $mayContainOtherContent = true;
-                                break 2;
-                            }
-
-                            // `<span>` is used to hold text formatting.
-                            break;
-
-                        case 'br':
-                        case 'a':
-                        case 'b':
-                        case 'em':
-                        case 'i':
-                        case 'strong':
-                        case 'u':
-                            // These elements are perfectly fine.
-                            break;
-
-                        default:
-                            $mayContainOtherContent = true;
-                            break 2;
+                    if ($this->mayContainOtherContent($parentLinkElement, $linebreaks)) {
+                        $mayContainOtherContent = true;
+                        break;
                     }
                 }
 
@@ -905,4 +862,34 @@ class HtmlInputNodeProcessor extends AbstractHtmlNodeProcessor
 
         return null;
     }
+
+    private function mayContainOtherContent(\DOMElement $element, int &$linebreaks): bool
+    {
+        switch ($element->nodeName) {
+            case 'br':
+                $linebreaks++;
+                break;
+
+            case 'span':
+                if ($element->getAttribute('class')) {
+                    return true;
+                }
+
+                // `<span>` is used to hold text formatting.
+                break;
+
+            case 'a':
+            case 'b':
+            case 'em':
+            case 'i':
+            case 'strong':
+            case 'u':
+                // These elements are perfectly fine.
+                break;
+
+            default:
+                return true;
+        }
+        return false;
+    }
 }
index f0a5c9428de5ca8560d35aed1a2e7596dc62a6ba..2de10c3eff7a0ab6172657f5e9b22855e32c9335 100644 (file)
@@ -72,6 +72,7 @@ class HtmlNodePlainLink
     {
         $this->standalone = false;
         $this->topLevelParent = null;
+        $this->aloneInParagraph = false;
 
         return $this;
     }
@@ -180,38 +181,38 @@ class HtmlNodePlainLink
                 $this->topLevelParent->parentNode->insertBefore($this->link, $this->topLevelParent);
                 DOMUtil::removeNode($this->topLevelParent);
             } else {
-                //Split at the link and replace the link with the metacode element.
+                $replaceNode = null;
+                $parent = $this->link;
                 $next = $this->findBr($this->link, 'nextSibling');
                 $previous = $this->findBr($this->link, 'previousSibling');
-                $replaceNode = null;
+                //link inside other elements(u, i, b, …)
+                while ($next === null && $previous === null && $parent !== $this->topLevelParent) {
+                    $parent = $parent->parentElement;
+                    $next = $this->findBr($parent, 'nextSibling');
+                    $previous = $this->findBr($parent, 'previousSibling');
+                }
 
                 if ($next !== null) {
                     $replaceNode = DOMUtil::splitParentsUntil(
-                        $this->link,
-                        $this->link->parentElement->parentElement,
+                        $parent,
+                        $this->topLevelParent->parentElement,
                         false
                     );
                 }
                 if ($previous !== null) {
                     $replaceNode = DOMUtil::splitParentsUntil(
-                        $this->link,
-                        $this->link->parentElement->parentElement
+                        $parent,
+                        $this->topLevelParent->parentElement
                     );
                 }
                 \assert($replaceNode instanceof \DOMElement);
 
                 //remove <br> from start and end of the new block elements
-                if ($replaceNode->nextSibling !== null) {
-                    $br = $this->findBr($replaceNode->nextSibling->firstChild, 'nextSibling');
-                    if ($br !== null) {
-                        DOMUtil::removeNode($br);
-                    }
+                if ($next !== null) {
+                    DOMUtil::removeNode($next);
                 }
-                if ($replaceNode->previousSibling !== null) {
-                    $br = $this->findBr($replaceNode->previousSibling->lastChild, 'previousSibling');
-                    if ($br !== null) {
-                        DOMUtil::removeNode($br);
-                    }
+                if ($previous !== null) {
+                    DOMUtil::removeNode($previous);
                 }
                 DOMUtil::replaceElement($replaceNode, $metacodeElement, false);