import { ContentBlock } from 'draft-js' ; import escapeRegExp from 'lodash/escapeRegExp' ; interface FindWithRegexCb { ( start , end ) : void ; } const whitespaceRegEx = /\s/ ; function checkForWhiteSpaceBeforeTrigger ( text , index ) { if ( index === 0 ) { return true ; } return whitespaceRegEx . test ( text [ index - 1 ] ) ; } function findInContentBlock ( regex , text , nonEntityStart , callback ) { let matchArr ; let start ; let prevLastIndex = regex . lastIndex ; while ( ( matchArr = regex . exec ( text ) ) !== null ) { if ( regex . lastIndex === prevLastIndex ) { break ; } prevLastIndex = regex . lastIndex ; start = nonEntityStart + matchArr . index ; const end = start + matchArr [ 0 ] . length ; if ( whitespaceRegEx . test ( text [ start ] ) ) { start += 1 ; } callback ( start , end ) ; } } function findInContentBlockWithWhitespace ( regex , text , nonEntityStart , callback ) { let matchArr ; let start ; let prevLastIndex = regex . lastIndex ; while ( ( matchArr = regex . exec ( text ) ) !== null ) { if ( regex . lastIndex === prevLastIndex ) { break ; } prevLastIndex = regex . lastIndex ; start = nonEntityStart + matchArr . index ; const end = start + matchArr [ 0 ] . length ; if ( checkForWhiteSpaceBeforeTrigger ( text , matchArr . index ) ) { callback ( start , end ) ; } } } const findWithRegex = ( regex , contentBlock , supportWhiteSpace , callback ) : void => { const contentBlockText = contentBlock . getText ( ) ; contentBlock . findEntityRanges ( ( character ) => ! character . getEntity ( ) , ( nonEntityStart , nonEntityEnd ) => { const text = contentBlockText . slice ( nonEntityStart , nonEntityEnd ) ; if ( supportWhiteSpace ) { findInContentBlockWithWhitespace ( regex , text , nonEntityStart , callback ) ; } else { findInContentBlock ( regex , text , nonEntityStart , callback ) ; } } ) ; } ; export default ( triggers , supportWhiteSpace , regExp ) : ( ( contentBlock : ContentBlock , callback : FindWithRegexCb ) => void ) => { const triggerPattern = `(${ triggers . map ( ( trigger ) => escapeRegExp ( trigger ) ) . join ( '|' ) })` ; const MENTION_REGEX = supportWhiteSpace ? new RegExp ( `${ triggerPattern }(${ regExp }|\\s)*` , 'g' ) : new RegExp ( `(\\s|^)${ triggerPattern }${ regExp }*` , 'g' ) ; return ( contentBlock , callback ) => { findWithRegex ( MENTION_REGEX , contentBlock , supportWhiteSpace , callback ) ; } ; } ;