@@ -872,6 +872,29 @@ class _ZulipContentParser {
872872 return descendant4.text.trim ();
873873 }
874874
875+ UserMentionNode ? parseUserMention (dom.Element element) {
876+ assert (_debugParserContext == _ParserContext .inline);
877+ assert (element.localName == 'span' );
878+ final debugHtmlNode = kDebugMode ? element : null ;
879+
880+ final classes = element.className.split (' ' )..sort ();
881+ assert (classes.contains ('user-mention' )
882+ || classes.contains ('user-group-mention' ));
883+ switch (classes) {
884+ case ['user-mention' || 'user-group-mention' ]:
885+ case ['silent' , 'user-mention' || 'user-group-mention' ]:
886+ break ;
887+ default :
888+ return null ;
889+ }
890+
891+ // TODO assert UserMentionNode can't contain LinkNode;
892+ // either a debug-mode check, or perhaps we can make expectations much
893+ // tighter on a UserMentionNode's contents overall.
894+ final nodes = parseInlineContentList (element.nodes);
895+ return UserMentionNode (nodes: nodes, debugHtmlNode: debugHtmlNode);
896+ }
897+
875898 /// The links found so far in the current block inline container.
876899 ///
877900 /// Empty is represented as null.
@@ -884,12 +907,12 @@ class _ZulipContentParser {
884907 return result;
885908 }
886909
887- static final _userMentionClassNameRegexp = () {
888- // This matches a class `user-mention` or `user-group-mention`,
889- // plus an optional class `silent`, appearing in either order.
890- const mentionClass = r"user(?:-group)?-mention" ;
891- return RegExp ("^(?:$ mentionClass (?: silent)?|silent $ mentionClass ) \$ " );
892- }( );
910+ /// Matches all className values that could be a UserMentionNode,
911+ /// and no className values that could be any other type of node.
912+ // Specifically, checks for `user-mention` or `user-group-mention`
913+ // as a member of the list.
914+ static final _userMentionClassNameRegexp = RegExp (
915+ r"(^| )" r"user(?:-group)?-mention" r"( |$)" );
893916
894917 static final _emojiClassNameRegexp = () {
895918 const specificEmoji = r"emoji(?:-[0-9a-f]+)+" ;
@@ -944,10 +967,7 @@ class _ZulipContentParser {
944967
945968 if (localName == 'span'
946969 && _userMentionClassNameRegexp.hasMatch (className)) {
947- // TODO assert UserMentionNode can't contain LinkNode;
948- // either a debug-mode check, or perhaps we can make expectations much
949- // tighter on a UserMentionNode's contents overall.
950- return UserMentionNode (nodes: nodes (), debugHtmlNode: debugHtmlNode);
970+ return parseUserMention (element) ?? unimplemented ();
951971 }
952972
953973 if (localName == 'span'
0 commit comments