Fix the behavior of mentions in the editor
authorAlexander Ebert <ebert@woltlab.com>
Sat, 29 Jul 2023 09:54:04 +0000 (11:54 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Sat, 29 Jul 2023 09:54:04 +0000 (11:54 +0200)
See https://www.woltlab.com/community/thread/300780-problem-when-trying-to-edit-the-first-letter-of-a-mention/

ts/WoltLabSuite/Core/Component/Ckeditor/Mention.ts
wcfsetup/install/files/js/WoltLabSuite/Core/Component/Ckeditor/Mention.js
wcfsetup/install/files/lib/system/html/input/node/HtmlInputNodeTextParser.class.php
wcfsetup/install/files/style/bbcode/userMention.scss

index b5c5628818c9e37b35e737cf7d2f5e4b70521b57..d7a0d43e98d9295add08a095297c5b7a9bfca249 100644 (file)
@@ -54,7 +54,7 @@ async function getPossibleMentions(query: string): Promise<Mention[]> {
     if (item.type === "user") {
       return {
         id: `@${item.username}`,
-        text: item.username,
+        text: `@${item.username}`,
         icon: item.avatarTag,
         objectId: item.userID,
         type: item.type,
@@ -62,7 +62,7 @@ async function getPossibleMentions(query: string): Promise<Mention[]> {
     } else {
       return {
         id: `@${item.name}`,
-        text: item.name,
+        text: `@${item.name}`,
         icon: '<fa-icon name="users"></fa-icon>',
         objectId: item.groupID,
         type: item.type,
index 552883ff22911e2601358b71caa9f479b579c5c1..4244f11f47c92ec95003cb43aae94be380e031fa 100644 (file)
@@ -28,7 +28,7 @@ define(["require", "exports", "../../Ajax/Backend", "../../Dom/Util", "./Event"]
             if (item.type === "user") {
                 return {
                     id: `@${item.username}`,
-                    text: item.username,
+                    text: `@${item.username}`,
                     icon: item.avatarTag,
                     objectId: item.userID,
                     type: item.type,
@@ -37,7 +37,7 @@ define(["require", "exports", "../../Ajax/Backend", "../../Dom/Util", "./Event"]
             else {
                 return {
                     id: `@${item.name}`,
-                    text: item.name,
+                    text: `@${item.name}`,
                     icon: '<fa-icon name="users"></fa-icon>',
                     objectId: item.groupID,
                     type: item.type,
index 045009d8f7c3dc53599615c88b929aae08cb7316..0dbef92689e10d63f3606b5d595a433754da8539 100644 (file)
@@ -152,7 +152,7 @@ class HtmlInputNodeTextParser
             }
 
             // check if node is within a code element or link
-            if ($this->hasCodeParent($node) || $this->hasLinkParent($node)) {
+            if ($this->hasCodeParent($node) || $this->hasLinkParent($node) || $this->hasMentionParent($node)) {
                 continue;
             }
 
@@ -692,6 +692,24 @@ class HtmlInputNodeTextParser
         return false;
     }
 
+    protected function hasMentionParent(\DOMText $text): bool
+    {
+        $parent = $text;
+        while ($parent = $parent->parentNode) {
+            if ($parent->nodeName !== 'woltlab-metacode') {
+                continue;
+            }
+
+            \assert($parent instanceof \DOMElement);
+            $type = $parent->getAttribute('data-name');
+            if ($type === 'user' || $type === 'group') {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     /**
      * Uses string markers to replace the matched text. This process prevents multiple
      * detections being applied to the same target and enables us to delay replacement.
index 84424f5f4287f5d422ff7f6c97fb03a2009f1187..c776109c49b2684344280a1811777990513542f0 100644 (file)
@@ -3,11 +3,11 @@
        background-color: var(--wcfSidebarBackground);
        border-radius: 2px;
        padding: 1px 5px;
+}
 
-       &::before {
-               content: "@";
-               /* avoids breaks between the '@' and the username, but still allows
+.userMention::before {
+       content: "@";
+       /* avoids breaks between the '@' and the username, but still allows
                   wrapping inside the username itself */
-               display: inline-block;
-       }
+       display: inline-block;
 }