@@ -286,6 +286,22 @@ static cmark_node *match(cmark_syntax_extension *ext, cmark_parser *parser,
286
286
// inline was finished in inlines.c.
287
287
}
288
288
289
+ static bool validate_protocol (char protocol [], uint8_t * data , int rewind ) {
290
+ size_t len = strlen (protocol );
291
+
292
+ // Check that the protocol matches
293
+ for (int i = 1 ; i <= len ; i ++ ) {
294
+ if (data [- rewind - i ] != protocol [len - i ]) {
295
+ return false;
296
+ }
297
+ }
298
+
299
+ char prev_char = data [- rewind - len - 1 ];
300
+
301
+ // Make sure the character before the protocol is non-alphanumeric
302
+ return !cmark_isalnum (prev_char );
303
+ }
304
+
289
305
static void postprocess_text (cmark_parser * parser , cmark_node * text , int offset ,
290
306
int depth , cmark_syntax_extension * ext ) {
291
307
// postprocess_text can recurse very deeply if there is a very long line of
@@ -296,6 +312,8 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
296
312
uint8_t * data = text -> as .literal .data ,
297
313
* at ;
298
314
size_t size = text -> as .literal .len ;
315
+ bool auto_mailto = true;
316
+ bool is_xmpp = false;
299
317
int rewind , max_rewind ,
300
318
nb = 0 , np = 0 , ns = 0 ;
301
319
@@ -322,8 +340,18 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
322
340
if (strchr (".+-_" , c ) != NULL )
323
341
continue ;
324
342
325
- if (c == '/' )
326
- ns ++ ;
343
+ if (strchr (":" , c ) != NULL ) {
344
+ if (validate_protocol ("mailto:" , data , rewind )) {
345
+ auto_mailto = false;
346
+ continue ;
347
+ }
348
+
349
+ if (validate_protocol ("xmpp:" , data , rewind )) {
350
+ auto_mailto = false;
351
+ is_xmpp = true;
352
+ continue ;
353
+ }
354
+ }
327
355
328
356
break ;
329
357
}
@@ -343,6 +371,8 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
343
371
nb ++ ;
344
372
else if (c == '.' && link_end < size - 1 && cmark_isalnum (data [link_end + 1 ]))
345
373
np ++ ;
374
+ else if (c == '/' && is_xmpp )
375
+ continue ;
346
376
else if (c != '-' && c != '_' )
347
377
break ;
348
378
}
@@ -368,7 +398,8 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
368
398
}
369
399
cmark_strbuf buf ;
370
400
cmark_strbuf_init (parser -> mem , & buf , 10 );
371
- cmark_strbuf_puts (& buf , "mailto:" );
401
+ if (auto_mailto )
402
+ cmark_strbuf_puts (& buf , "mailto:" );
372
403
cmark_strbuf_put (& buf , data - rewind , (bufsize_t )(link_end + rewind ));
373
404
link_node -> as .link .url = cmark_chunk_buf_detach (& buf );
374
405
0 commit comments