@@ -107,9 +107,30 @@ const emojiMarkdownPlugin = () => {
107107 return transform ;
108108} ;
109109
110+ const mentionsMarkdownPlugin = ( mentionedUsersRegex : RegExp ) => ( ) => {
111+ function replace ( match : RegExpMatchArray | null ) {
112+ return {
113+ children : [ { type : 'text' , value : match } ] ,
114+ type : 'mention' ,
115+ } ;
116+ }
117+
118+ const transform = < T extends unknown > ( markdownAST : T ) => {
119+ findAndReplace ( markdownAST , mentionedUsersRegex , replace ) ;
120+ return markdownAST ;
121+ } ;
122+
123+ return transform ;
124+ } ;
125+
126+ const Mention : React . FC = ( { children } ) => (
127+ < span className = 'str-chat__message-mention' > { children } </ span >
128+ ) ;
129+
110130export const renderText = < Us extends DefaultUserType < Us > = DefaultUserType > (
111131 text ?: string ,
112132 mentioned_users ?: UserResponse < Us > [ ] ,
133+ MentionComponent : React . ComponentType = Mention ,
113134) => {
114135 // take the @ mentions and turn them into markdown?
115136 // translate links
@@ -146,27 +167,32 @@ export const renderText = <Us extends DefaultUserType<Us> = DefaultUserType>(
146167 newText = newText . replace ( value , `[${ displayLink } ](${ encodeURI ( href ) } )` ) ;
147168 } ) ;
148169
149- if ( mentioned_users && mentioned_users . length ) {
150- for ( let i = 0 ; i < mentioned_users . length ; i ++ ) {
151- let username = mentioned_users [ i ] . name || mentioned_users [ i ] . id ;
152-
153- if ( username ) {
154- username = escapeRegExp ( username ) ;
155- }
170+ const plugins = [ emojiMarkdownPlugin ] ;
156171
157- const nameMarkdown = `**@${ username } **` ;
158- const nameRegex = new RegExp ( `@${ username } ` , 'g' ) ;
172+ const mentioned_usernames = mentioned_users
173+ ?. map ( ( user ) => user . name || user . id )
174+ . filter ( Boolean )
175+ . map ( escapeRegExp ) ;
159176
160- newText = newText . replace ( nameRegex , nameMarkdown ) ;
161- }
177+ if ( mentioned_usernames ?. length ) {
178+ const mentionedUsersRegex = new RegExp (
179+ mentioned_usernames . map ( ( username ) => `@${ username } ` ) . join ( '|' ) ,
180+ 'g' ,
181+ ) ;
182+ plugins . push ( mentionsMarkdownPlugin ( mentionedUsersRegex ) ) ;
162183 }
163184
185+ const renderers = {
186+ ...markDownRenderers ,
187+ mention : MentionComponent ,
188+ } ;
189+
164190 return (
165191 < ReactMarkdown
166192 allowedTypes = { allowedMarkups }
167193 escapeHtml = { true }
168- plugins = { [ emojiMarkdownPlugin ] }
169- renderers = { markDownRenderers }
194+ plugins = { plugins }
195+ renderers = { renderers }
170196 source = { newText }
171197 transformLinkUri = { ( uri ) =>
172198 uri . startsWith ( 'app://' ) ? uri : RootReactMarkdown . uriTransformer ( uri )
0 commit comments