mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	markdown: Fix invalid mention bug for user mention.
Modifies `UserMentionPattern` to inherit from InlineProcessor instead of Pattern. This change is done because Pattern stopped checking for matching patterns as soon as it found a match which was not a valid user. Due to this all the subsequent user mention failed. This bug was only present in backend renderring due to markdown.inlinepatterns.Pattern. This was reported as issue #17535. These changes were tested locally in dev server and by adding some new markdown tests to test these.
This commit is contained in:
		
				
					committed by
					
						
						Tim Abbott
					
				
			
			
				
	
			
			
			
						parent
						
							42aea49784
						
					
				
				
					commit
					c8979a5100
				
			@@ -1796,8 +1796,10 @@ class RealmFilterPattern(markdown.inlinepatterns.Pattern):
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserMentionPattern(markdown.inlinepatterns.Pattern):
 | 
			
		||||
    def handleMatch(self, m: Match[str]) -> Optional[Element]:
 | 
			
		||||
class UserMentionPattern(markdown.inlinepatterns.InlineProcessor):
 | 
			
		||||
    def handleMatch(  # type: ignore[override] # supertype incompatible with supersupertype
 | 
			
		||||
        self, m: Match[str], data: str
 | 
			
		||||
    ) -> Union[Tuple[None, None, None], Tuple[Element, int, int]]:
 | 
			
		||||
        match = m.group("match")
 | 
			
		||||
        silent = m.group("silent") == "_"
 | 
			
		||||
 | 
			
		||||
@@ -1806,7 +1808,7 @@ class UserMentionPattern(markdown.inlinepatterns.Pattern):
 | 
			
		||||
            if match.startswith("**") and match.endswith("**"):
 | 
			
		||||
                name = match[2:-2]
 | 
			
		||||
            else:
 | 
			
		||||
                return None
 | 
			
		||||
                return None, None, None
 | 
			
		||||
 | 
			
		||||
            wildcard = mention.user_mention_matches_wildcard(name)
 | 
			
		||||
 | 
			
		||||
@@ -1827,7 +1829,7 @@ class UserMentionPattern(markdown.inlinepatterns.Pattern):
 | 
			
		||||
                user_id = str(user["id"])
 | 
			
		||||
            else:
 | 
			
		||||
                # Don't highlight @mentions that don't refer to a valid user
 | 
			
		||||
                return None
 | 
			
		||||
                return None, None, None
 | 
			
		||||
 | 
			
		||||
            el = Element("span")
 | 
			
		||||
            el.set("data-user-id", user_id)
 | 
			
		||||
@@ -1838,8 +1840,8 @@ class UserMentionPattern(markdown.inlinepatterns.Pattern):
 | 
			
		||||
                el.set("class", "user-mention")
 | 
			
		||||
                text = f"@{text}"
 | 
			
		||||
            el.text = markdown.util.AtomicString(text)
 | 
			
		||||
            return el
 | 
			
		||||
        return None
 | 
			
		||||
            return el, m.start(), m.end()
 | 
			
		||||
        return None, None, None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserGroupMentionPattern(markdown.inlinepatterns.Pattern):
 | 
			
		||||
 
 | 
			
		||||
@@ -1845,6 +1845,36 @@ class MarkdownTest(ZulipTestCase):
 | 
			
		||||
        )
 | 
			
		||||
        self.assertEqual(msg.mentions_user_ids, set())
 | 
			
		||||
 | 
			
		||||
    def test_mention_invalid_followed_by_valid(self) -> None:
 | 
			
		||||
        sender_user_profile = self.example_user("othello")
 | 
			
		||||
        user_profile = self.example_user("hamlet")
 | 
			
		||||
        msg = Message(sender=sender_user_profile, sending_client=get_client("test"))
 | 
			
		||||
        user_id = user_profile.id
 | 
			
		||||
 | 
			
		||||
        content = "@**Invalid user** and @**King Hamlet**"
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            render_markdown(msg, content),
 | 
			
		||||
            '<p>@<strong>Invalid user</strong> and <span class="user-mention" '
 | 
			
		||||
            f'data-user-id="{user_id}">'
 | 
			
		||||
            "@King Hamlet</span></p>",
 | 
			
		||||
        )
 | 
			
		||||
        self.assertEqual(msg.mentions_user_ids, {user_profile.id})
 | 
			
		||||
 | 
			
		||||
    def test_silent_mention_invalid_followed_by_valid(self) -> None:
 | 
			
		||||
        sender_user_profile = self.example_user("othello")
 | 
			
		||||
        user_profile = self.example_user("hamlet")
 | 
			
		||||
        msg = Message(sender=sender_user_profile, sending_client=get_client("test"))
 | 
			
		||||
        user_id = user_profile.id
 | 
			
		||||
 | 
			
		||||
        content = "@_**Invalid user** and @_**King Hamlet**"
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            render_markdown(msg, content),
 | 
			
		||||
            '<p>@_<strong>Invalid user</strong> and <span class="user-mention silent" '
 | 
			
		||||
            f'data-user-id="{user_id}">'
 | 
			
		||||
            "King Hamlet</span></p>",
 | 
			
		||||
        )
 | 
			
		||||
        self.assertEqual(msg.mentions_user_ids, set())
 | 
			
		||||
 | 
			
		||||
    def test_possible_mentions(self) -> None:
 | 
			
		||||
        def assert_mentions(content: str, names: Set[str], has_wildcards: bool = False) -> None:
 | 
			
		||||
            self.assertEqual(possible_mentions(content), (names, has_wildcards))
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user