99const emailUserName = '[\\w+\\.~$_-]+' ;
1010const schema = `(\\w{2,15}:\\/\\/)` ;
1111// something.tld OR 123.123.123.123
12- const userName = '^@\\w+\\.?\\w*' ;
13- const domain = `((?:\\w+\\.[a-zA-Z]+(?<!${ userName } ))+(?:[^:\\/\\s]+)|(?:\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}))` ;
12+ const domain = `((?:\\w+\\.[a-zA-Z]+)+(?:[^:\\/\\s]+)|(?:\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}))` ;
1413const port = `(:[0-9]{1,5})` ;
1514const path = `((?:\\/)?[^?\\s]+)` ;
1615const queryString = `(\\?[^#\\s]+)` ;
@@ -44,10 +43,19 @@ interface Link {
4443 * */
4544const removeMarkdownLinksFromText = ( input : string ) => input . replace ( / \[ [ \w \s ] + \] \( .* \) / g, '' ) ;
4645
46+ /**
47+ * Hermes doesn't support lookbehind, so this is done separately to avoid
48+ * parsing user names as links.
49+ * */
50+ const removeUserNamesFromText = ( input : string ) => input . replace ( / ^ @ \w + \. ? \w / , '' ) ;
51+
4752export const parseLinksFromText = ( input : string ) : Link [ ] => {
4853 let matches ;
4954
50- const inputWithoutMarkdownLinks = removeMarkdownLinksFromText ( input ) ;
55+ const strippedInput = [ removeMarkdownLinksFromText , removeUserNamesFromText ] . reduce (
56+ ( acc , fn ) => fn ( acc ) ,
57+ input ,
58+ ) ;
5159
5260 const results : Link [ ] = [ ] ;
5361
@@ -62,7 +70,7 @@ export const parseLinksFromText = (input: string): Link[] => {
6270 * to avoid overlapping matches being duplicated in the output.
6371 * */
6472 const linkRegex = new RegExp ( `${ fqdnLinkPattern } |${ schemePrefixedLinkPattern } ` , 'gi' ) ;
65- while ( ( matches = linkRegex . exec ( inputWithoutMarkdownLinks ) ) !== null ) {
73+ while ( ( matches = linkRegex . exec ( strippedInput ) ) !== null ) {
6674 const [
6775 raw ,
6876 fqdnScheme = '' ,
0 commit comments