@@ -18,24 +18,6 @@ function mentionStart(src: string) {
1818 return src . indexOf ( '<' ) ;
1919}
2020
21- function mentionTokenizer ( this : any , src : string , options : MentionOptions = { } ) {
22- const trigger = options . triggerChar ?? '@' ;
23- // Build dynamic regex for `<@id>`, `<@id|label>`, `<@id|>`
24- // Added forward slash (/) to the character class for IDs
25- const re = new RegExp ( `^<\\${ trigger } ([\\w.\\-:/]+)(?:\\|([^>]*))?>` ) ;
26- const m = re . exec ( src ) ;
27- if ( ! m ) return ;
28-
29- const [ , id , label ] = m ;
30- return {
31- type : 'mention' ,
32- raw : m [ 0 ] ,
33- triggerChar : trigger ,
34- id,
35- label : label && label . length > 0 ? label : id
36- } ;
37- }
38-
3921function mentionRenderer ( token : any , options : MentionOptions = { } ) {
4022 const trigger = options . triggerChar ?? '@' ;
4123 const cls = options . className ?? 'mention' ;
@@ -55,12 +37,27 @@ function mentionRenderer(token: any, options: MentionOptions = {}) {
5537}
5638
5739export function mentionExtension ( opts : MentionOptions = { } ) {
40+ // Build the regex once per extension instance (called 3× at module load for @, #, $).
41+ // mentionStart fires on every '<' in the document, so keeping allocation out of the
42+ // tokenizer is meaningful during streaming.
43+ const trigger = opts . triggerChar ?? '@' ;
44+ const re = new RegExp ( `^<\\${ trigger } ([\\w.\\-:/]+)(?:\\|([^>]*))?>` ) ;
45+
5846 return {
5947 name : 'mention' ,
6048 level : 'inline' as const ,
6149 start : mentionStart ,
6250 tokenizer ( src : string ) {
63- return mentionTokenizer . call ( this , src , opts ) ;
51+ const m = re . exec ( src ) ;
52+ if ( ! m ) return ;
53+ const [ , id , label ] = m ;
54+ return {
55+ type : 'mention' ,
56+ raw : m [ 0 ] ,
57+ triggerChar : trigger ,
58+ id,
59+ label : label && label . length > 0 ? label : id
60+ } ;
6461 } ,
6562 renderer ( token : any ) {
6663 return mentionRenderer ( token , opts ) ;
0 commit comments