diff --git a/__tests__/ExpensiMark-HTML-test.js b/__tests__/ExpensiMark-HTML-test.js
index a98e35aa..6adf8420 100644
--- a/__tests__/ExpensiMark-HTML-test.js
+++ b/__tests__/ExpensiMark-HTML-test.js
@@ -609,6 +609,60 @@ test('Test a url ending with a closing parentheses autolinks correctly', () => {
expect(parser.replace(testString)).toBe(resultString);
});
+test('Test urls autolinks correctly', () => {
+ let testString = 'test@expensify.com https://www.expensify.com\n' +
+ 'test@expensify.com-https://www.expensify.com\n' +
+ 'test@expensify.com/https://www.expensify.com\n' +
+ 'test@expensify.com?https://www.expensify.com\n' +
+ 'test@expensify.com>https://www.expensify.com\n' +
+ 'https://staging.new.expensify.com/details/test@expensify.com\n' +
+ 'staging.new.expensify.com/details\n\n' +
+ 'https://www.expensify.com?name=test&email=test@expensify.com\n' +
+ 'https://staging.new.expensify.com/details?login=testing@gmail.com\n' +
+ 'staging.new.expensify.com/details?login=testing@gmail.com\n' +
+ 'http://necolas.github.io/react-native-web/docs/?path=/docs/components-pressable--disabled\n' +
+ '-https://www.expensify.com /https://www.expensify.com @https://www.expensify.com\n' +
+ 'expensify.com -expensify.com @expensify.com\n' +
+ 'https//www.expensify.com\n' +
+ '//www.expensify.com?name=test&email=test@expensify.com\n' +
+ '//staging.new.expensify.com/details?login=testing@gmail.com\n' +
+ '/details?login=testing@gmail.com\n' +
+ '?name=test&email=test@expensify.com\n\n' +
+ 'example.com/https://www.expensify.com\n' +
+ 'test@gmail.com staging.new.expensify.com/details?login=testing@gmail.com&redirectUrl=https://google.com\n' +
+ 'test@gmail.com //staging.new.expensify.com/details?login=testing@gmail.com&redirectUrl=https://google.com\n' +
+ 'test@gmail.com-https://staging.new.expensify.com/details?login=testing@gmail.com&redirectUrl=https://google.com\n' +
+ 'test@gmail.com/https://example.com/google@email.com?email=asd@email.com\n' +
+ 'test@gmail.com/test@gmail.com/https://example.com/google@email.com?email=asd@email.com';
+
+ let resultString = 'test@expensify.com https://www.expensify.com
' +
+ 'test@expensify.com-https://www.expensify.com
' +
+ 'test@expensify.com/https://www.expensify.com
' +
+ 'test@expensify.com?https://www.expensify.com
' +
+ 'test@expensify.com>https://www.expensify.com
' +
+ 'https://staging.new.expensify.com/details/test@expensify.com
' +
+ 'staging.new.expensify.com/details
'+
+ 'https://www.expensify.com?name=test&email=test@expensify.com
' +
+ 'https://staging.new.expensify.com/details?login=testing@gmail.com
' +
+ 'staging.new.expensify.com/details?login=testing@gmail.com
' +
+ 'http://necolas.github.io/react-native-web/docs/?path=/docs/components-pressable--disabled
' +
+ '-https://www.expensify.com /https://www.expensify.com @https://www.expensify.com
' +
+ 'expensify.com -expensify.com @expensify.com
' +
+ 'https//www.expensify.com
' +
+ '//www.expensify.com?name=test&email=test@expensify.com
' +
+ '//staging.new.expensify.com/details?login=testing@gmail.com
' +
+ '/details?login=testing@gmail.com
' +
+ '?name=test&email=test@expensify.com
' +
+ 'example.com/https://www.expensify.com
' +
+ 'test@gmail.com staging.new.expensify.com/details?login=testing@gmail.com&redirectUrl=https://google.com
' +
+ 'test@gmail.com //staging.new.expensify.com/details?login=testing@gmail.com&redirectUrl=https://google.com
' +
+ 'test@gmail.com-https://staging.new.expensify.com/details?login=testing@gmail.com&redirectUrl=https://google.com
' +
+ 'test@gmail.com/https://example.com/google@email.com?email=asd@email.com
' +
+ 'test@gmail.com/test@gmail.com/https://example.com/google@email.com?email=asd@email.com';
+
+ expect(parser.replace(testString)).toBe(resultString);
+});
+
test('Test markdown style email link with various styles', () => {
const testString = 'Go to ~[Expensify](concierge@expensify.com)~ '
+ '_[Expensify](concierge@expensify.com)_ '
diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js
index 0c34246f..255534bc 100644
--- a/lib/ExpensiMark.js
+++ b/lib/ExpensiMark.js
@@ -446,12 +446,6 @@ export default class ExpensiMark {
let startIndex = 0;
while (match !== null) {
- // we want to avoid matching email address domains
- let abort = false;
- if ((match.index !== 0) && (textToCheck[match.index - 1] === '@')) {
- abort = true;
- }
-
// we want to avoid matching ending ) unless it is a closing parenthesis for the URL
if (textToCheck[(match.index + match[2].length) - 1] === ')' && !match[2].includes('(')) {
match[0] = match[0].substr(0, match[0].length - 1);
@@ -476,9 +470,28 @@ export default class ExpensiMark {
}
replacedText = replacedText.concat(textToCheck.substr(startIndex, (match.index - startIndex)));
+ // we want to avoid matching email address domains
+ let abort = false;
+ let shouldRetryByAtSign = false;
+
+ if ((match.index !== 0) && (textToCheck[match.index - 1] === '@')) {
+ const domainRegex = new RegExp('^(([a-z-0-9]+\\.)+[a-z]{2,})(\\S*)', 'i');
+ const domainMatch = domainRegex.exec(match[2]);
+
+ // e.g. test@expensify.com/https://www.test.com
+ // If the matched string faces @ sign before it,
+ // We will retry to apply autolink rule to the string(e.g. /https://www.test.com) except for domain(e.g. expensify.com) after @ sign.
+ if ((domainMatch !== null) && (domainMatch[3] !== '')) {
+ shouldRetryByAtSign = true;
+ replacedText = replacedText.concat(domainMatch[1] + this.replace(domainMatch[3], {filterRules: ['autolink']}));
+ } else {
+ abort = true;
+ }
+ }
+
if (abort || match[1].includes('
')) { replacedText = replacedText.concat(textToCheck.substr(match.index, (match[0].length))); - } else { + } else if (!shouldRetryByAtSign) { const urlRegex = new RegExp(`^${LOOSE_URL_REGEX}$|^${URL_REGEX}$`, 'i'); // `match[1]` contains the text inside the [] of the markdown e.g. [example](https://example.com)