Skip to content

Commit

Permalink
Merge pull request #573 from Antasel/fix-#16762-parse-deep-link
Browse files Browse the repository at this point in the history
  • Loading branch information
cead22 authored Sep 11, 2023
2 parents e63d06e + bfa8f11 commit 191c0c8
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 8 deletions.
105 changes: 105 additions & 0 deletions __tests__/ExpensiMark-HTML-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,111 @@ test('Test a url ending with a closing parentheses autolinks correctly', () => {
expect(parser.replace(testString)).toBe(resultString);
});

test('Test urls autolinks correctly', () => {
const testCases = [
{
testString: '[email protected] https://www.expensify.com',
resultString: '<a href="mailto:[email protected]">[email protected]</a> <a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">https://www.expensify.com</a>',
},
{
testString: '[email protected]://www.expensify.com',
resultString: '<a href="mailto:[email protected]">[email protected]</a>-<a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">https://www.expensify.com</a>',
},
{
testString: '[email protected]/https://www.expensify.com',
resultString: '<a href="mailto:[email protected]">[email protected]</a>/<a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">https://www.expensify.com</a>',
},
{
testString: '[email protected]?https://www.expensify.com',
resultString: '<a href="mailto:[email protected]">[email protected]</a>?<a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">https://www.expensify.com</a>',
},
{
testString: '[email protected]>https://www.expensify.com',
resultString: '<a href="mailto:[email protected]">[email protected]</a>&gt;<a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">https://www.expensify.com</a>',
},
{
testString: 'https://staging.new.expensify.com/details/[email protected]',
resultString: '<a href="https://staging.new.expensify.com/details/[email protected]" target="_blank" rel="noreferrer noopener">https://staging.new.expensify.com/details/[email protected]</a>',
},
{
testString: 'staging.new.expensify.com/details',
resultString: '<a href="https://staging.new.expensify.com/details" target="_blank" rel="noreferrer noopener">staging.new.expensify.com/details</a>',
},
{
testString: 'https://www.expensify.com?name=test&[email protected]',
resultString: '<a href="https://www.expensify.com?name=test&amp;[email protected]" target="_blank" rel="noreferrer noopener">https://www.expensify.com?name=test&amp;[email protected]</a>',
},
{
testString: 'https://staging.new.expensify.com/[email protected]',
resultString: '<a href="https://staging.new.expensify.com/[email protected]" target="_blank" rel="noreferrer noopener">https://staging.new.expensify.com/[email protected]</a>',
},
{
testString: 'staging.new.expensify.com/[email protected]',
resultString: '<a href="https://staging.new.expensify.com/[email protected]" target="_blank" rel="noreferrer noopener">staging.new.expensify.com/[email protected]</a>',
},
{
testString: 'http://necolas.github.io/react-native-web/docs/?path=/docs/components-pressable--disabled',
resultString: '<a href="http://necolas.github.io/react-native-web/docs/?path=/docs/components-pressable--disabled" target="_blank" rel="noreferrer noopener">http://necolas.github.io/react-native-web/docs/?path=/docs/components-pressable--disabled</a>',
},
{
testString: '-https://www.expensify.com /https://www.expensify.com @https://www.expensify.com',
resultString: '-<a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">https://www.expensify.com</a> /<a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">https://www.expensify.com</a> @https://www.expensify.com',
},
{
testString: 'expensify.com -expensify.com @expensify.com',
resultString: '<a href="https://expensify.com" target="_blank" rel="noreferrer noopener">expensify.com</a> -<a href="https://expensify.com" target="_blank" rel="noreferrer noopener">expensify.com</a> @expensify.com',
},
{
testString: 'https//www.expensify.com',
resultString: 'https//<a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">www.expensify.com</a>',
},
{
testString: '//www.expensify.com?name=test&[email protected]',
resultString: '//<a href="https://www.expensify.com?name=test&amp;[email protected]" target="_blank" rel="noreferrer noopener">www.expensify.com?name=test&amp;[email protected]</a>',
},
{
testString: '//staging.new.expensify.com/[email protected]',
resultString: '//<a href="https://staging.new.expensify.com/[email protected]" target="_blank" rel="noreferrer noopener">staging.new.expensify.com/[email protected]</a>',
},
{
testString: '/[email protected]',
resultString: '/details?login=<a href="mailto:[email protected]">[email protected]</a>',
},
{
testString: '?name=test&[email protected]',
resultString: '?name=test&amp;email=<a href="mailto:[email protected]">[email protected]</a>',
},
{
testString: 'example.com/https://www.expensify.com',
resultString: '<a href="https://example.com/https://www.expensify.com" target="_blank" rel="noreferrer noopener">example.com/https://www.expensify.com</a>',
},
{
testString: '[email protected] staging.new.expensify.com/[email protected]&redirectUrl=https://google.com',
resultString: '<a href="mailto:[email protected]">[email protected]</a> <a href="https://staging.new.expensify.com/[email protected]&amp;redirectUrl=https://google.com" target="_blank" rel="noreferrer noopener">staging.new.expensify.com/[email protected]&amp;redirectUrl=https://google.com</a>',
},
{
testString: '[email protected] //staging.new.expensify.com/[email protected]&redirectUrl=https://google.com',
resultString: '<a href="mailto:[email protected]">[email protected]</a> //<a href="https://staging.new.expensify.com/[email protected]&amp;redirectUrl=https://google.com" target="_blank" rel="noreferrer noopener">staging.new.expensify.com/[email protected]&amp;redirectUrl=https://google.com</a>',
},
{
testString: '[email protected]://staging.new.expensify.com/[email protected]&redirectUrl=https://google.com',
resultString: '<a href="mailto:[email protected]">[email protected]</a>-<a href="https://staging.new.expensify.com/[email protected]&amp;redirectUrl=https://google.com" target="_blank" rel="noreferrer noopener">https://staging.new.expensify.com/[email protected]&amp;redirectUrl=https://google.com</a>',
},
{
testString: '[email protected]/https://example.com/[email protected][email protected]',
resultString: '<a href="mailto:[email protected]\">[email protected]</a>/<a href="https://example.com/[email protected][email protected]" target="_blank" rel="noreferrer noopener">https://example.com/[email protected][email protected]</a>',
},
{
testString: '[email protected]/[email protected]/https://example.com/[email protected][email protected]',
resultString: '<a href="mailto:[email protected]">[email protected]</a>/<a href="mailto:[email protected]">[email protected]</a>/<a href="https://example.com/[email protected][email protected]" target="_blank" rel="noreferrer noopener">https://example.com/[email protected][email protected]</a>',
},
];

testCases.forEach(testCase => {
expect(parser.replace(testCase.testString)).toBe(testCase.resultString);
});
});

test('Test markdown style email link with various styles', () => {
const testString = 'Go to ~[Expensify]([email protected])~ '
+ '_[Expensify]([email protected])_ '
Expand Down
32 changes: 24 additions & 8 deletions lib/ExpensiMark.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -476,9 +470,31 @@ export default class ExpensiMark {
}
replacedText = replacedText.concat(textToCheck.substr(startIndex, (match.index - startIndex)));

if (abort || match[1].includes('<pre>')) {
// We want to avoid matching domains in email addresses so we don't render them as URLs,
// but we need to check if there are valid URLs after the email address and render them accordingly,
// e.g. [email protected]/https://www.test.com
let isDoneMatching = false;
let shouldApplyAutoLinkAgain = true;

// If we find a URL with a leading @ sign, we need look for other domains in the rest of the string
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]);

// If we find another domain in the remainder of the string, we apply the auto link rule again and set a flag to avoid re-doing below.
if ((domainMatch !== null) && (domainMatch[3] !== '')) {
replacedText = replacedText.concat(domainMatch[1] + this.replace(domainMatch[3], {filterRules: ['autolink']}));
shouldApplyAutoLinkAgain = false;
} else {
// Otherwise, we're done applying rules
isDoneMatching = true;
}
}

// We don't want to apply link rule if match[1] contains the code block inside the [] of the markdown e.g. [```example```](https://example.com)
if (isDoneMatching || match[1].includes('<pre>')) {
replacedText = replacedText.concat(textToCheck.substr(match.index, (match[0].length)));
} else {
} else if (shouldApplyAutoLinkAgain) {
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)
Expand Down

0 comments on commit 191c0c8

Please sign in to comment.