From fc9b7bc36168412a7a8114584b692fbe817cf634 Mon Sep 17 00:00:00 2001 From: Eric Han Date: Tue, 16 May 2023 21:40:37 +0800 Subject: [PATCH 1/6] fix conflict --- __tests__/ExpensiMark-HTML-test.js | 2 +- __tests__/Str-test.js | 12 ++++++++++++ lib/ExpensiMark.js | 12 +++++------- lib/Url.js | 2 +- lib/str.js | 17 +++++++++++++++++ 5 files changed, 36 insertions(+), 9 deletions(-) diff --git a/__tests__/ExpensiMark-HTML-test.js b/__tests__/ExpensiMark-HTML-test.js index 8248d215..476655e2 100644 --- a/__tests__/ExpensiMark-HTML-test.js +++ b/__tests__/ExpensiMark-HTML-test.js @@ -395,7 +395,7 @@ test('Test url replacements', () => { + 'https://expensify.cash/#/r/1234 ' + 'https://github.com/Expensify/ReactNativeChat/pull/6.45 ' + 'https://github.com/Expensify/Expensify/issues/143,231 ' - + 'testRareTLDs.beer ' + + 'testRareTLDs.beer ' + 'test@expensify.com ' + 'test.completelyFakeTLD ' + 'https://www.expensify.com/_devportal/tools/logSearch/#query=request_id:(%22Ufjjim%22)+AND+timestamp:[2021-01-08T03:48:10.389Z+TO+2021-01-08T05:48:10.389Z]&index=logs_expensify-008878) ' diff --git a/__tests__/Str-test.js b/__tests__/Str-test.js index 1c843951..d08fbffe 100644 --- a/__tests__/Str-test.js +++ b/__tests__/Str-test.js @@ -84,3 +84,15 @@ describe('Str.isValidMention', () => { expect(Str.isValidMention('"@username@expensify.com"')).toBeTruthy(); }); }); + +describe('Str.normalizeWebsiteOfUrl', () => { + it('Normalize website of url to lower case and add missing https:// protocol', () => { + expect(Str.normalizeWebsiteOfUrl('https://google.com')).toBe('https://google.com'); + expect(Str.normalizeWebsiteOfUrl('google.com')).toBe('https://google.com'); + expect(Str.normalizeWebsiteOfUrl('Https://google.com')).toBe('https://google.com'); + expect(Str.normalizeWebsiteOfUrl('https://GOOgle.com')).toBe('https://google.com'); + expect(Str.normalizeWebsiteOfUrl('FOO.com/blah_BLAH')).toBe('https://foo.com/blah_BLAH'); + expect(Str.normalizeWebsiteOfUrl('http://FOO.com/blah_BLAH')).toBe('http://foo.com/blah_BLAH'); + expect(Str.normalizeWebsiteOfUrl('HTtp://FOO.com/blah_BLAH')).toBe('http://foo.com/blah_BLAH'); + }); +}); diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index 52b90400..98bd6133 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -115,13 +115,11 @@ export default class ExpensiMark { // We use a function here to check if there is already a https:// on the link. // If there is not, we force the link to be absolute by prepending '//' to the target. - replacement: (match, g1, g2, g3) => { + replacement: (match, g1, g2) => { if (g1.match(CONST.REG_EXP.EMOJIS) || !g1.trim()) { return match; } - - const href = g3 ? g2.replace(g3, g3.toLowerCase()) : `https://${g2}`; - return `${g1.trim()}`; + return `${g1.trim()}`; }, }, @@ -156,8 +154,8 @@ export default class ExpensiMark { // We use a function here to check if there is already a https:// on the link. // If there is not, we force the link to be absolute by prepending '//' to the target. - replacement: (match, g1, g2, g3) => { - const href = g3 ? g2.replace(g3, g3.toLowerCase()) : `https://${g2}`; + replacement: (match, g1, g2) => { + const href = Str.normalizeWebsiteOfUrl(g2); return `${g1}${g2}${g1}`; }, }, @@ -465,7 +463,7 @@ export default class ExpensiMark { filterRules: ['bold', 'strikethrough', 'italic'], shouldEscapeText: false, }); - replacedText = replacedText.concat(replacement(match[0], linkText, match[2], match[3])); + replacedText = replacedText.concat(replacement(match[0], linkText, match[2])); } startIndex = match.index + (match[0].length); diff --git a/lib/Url.js b/lib/Url.js index 2554d91c..495c1f38 100644 --- a/lib/Url.js +++ b/lib/Url.js @@ -7,7 +7,7 @@ const addEscapedChar = reg => `(?:${reg}|&(?:amp|quot|#x27);)`; const URL_PATH_REGEX = `(?:${addEscapedChar('[.,=(+$!*]')}?\\/${addEscapedChar('[-\\w$@.+!*:(),=%~]')}*${addEscapedChar('[-\\w~@:%)]')}|\\/)*`; const URL_PARAM_REGEX = `(?:\\?${addEscapedChar('[-\\w$@.+!*()\\/,=%{}:;\\[\\]\\|_|~]')}*)?`; const URL_FRAGMENT_REGEX = `(?:#${addEscapedChar('[-\\w$@.+!*()[\\],=%;\\/:~]')}*)?`; -const URL_REGEX = `(${URL_WEBSITE_REGEX}${URL_PATH_REGEX}(?:${URL_PARAM_REGEX}|${URL_FRAGMENT_REGEX})*)`; +const URL_REGEX = `((${URL_WEBSITE_REGEX})${URL_PATH_REGEX}(?:${URL_PARAM_REGEX}|${URL_FRAGMENT_REGEX})*)`; const URL_REGEX_WITH_REQUIRED_PROTOCOL = URL_REGEX.replace(`${URL_PROTOCOL_REGEX}?`, URL_PROTOCOL_REGEX); diff --git a/lib/str.js b/lib/str.js index 7cab4f9f..04b5c042 100644 --- a/lib/str.js +++ b/lib/str.js @@ -3,6 +3,7 @@ import _ from 'underscore'; import {AllHtmlEntities} from 'html-entities'; import replaceAll from 'string.prototype.replaceall'; import {CONST} from './CONST'; +import {URL_REGEX} from './Url'; const REMOVE_SMS_DOMAIN_PATTERN = new RegExp(`@${CONST.SMS.DOMAIN}`, 'gi'); @@ -1021,6 +1022,22 @@ const Str = { return (typeof url === 'string' && url.startsWith('/')) ? url : `/${url}`; }, + /** + * Takes in a URL, returns it with website in lower case and adds missing https:// protocol + * + * @param {url} url The URL to be formatted + * @returns {String} The formatted URL + */ + normalizeWebsiteOfUrl(url) { + const regex = new RegExp(`^${URL_REGEX}$`, 'i'); + const match = regex.exec(url); + if (!match) { + return url; + } + const website = match[3] ? match[2] : `https://${match[2]}`; + return website.toLowerCase() + this.cutBefore(match[1], match[2]); + }, + /** * Checks if parameter is a string or function * if it is a function then we will call it with From 19da2211b4335d0c7cc7ff4efce6cb47244616d9 Mon Sep 17 00:00:00 2001 From: Eric Han <117511920+eh2077@users.noreply.github.com> Date: Tue, 16 May 2023 23:56:49 +0800 Subject: [PATCH 2/6] Update lib/str.js Co-authored-by: Fedi Rajhi --- lib/str.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/str.js b/lib/str.js index 04b5c042..6f22b1a4 100644 --- a/lib/str.js +++ b/lib/str.js @@ -1023,7 +1023,7 @@ const Str = { }, /** - * Takes in a URL, returns it with website in lower case and adds missing https:// protocol + * * Formats a URL by converting the domain name to lowercase and adding the missing 'https://' protocol. * * @param {url} url The URL to be formatted * @returns {String} The formatted URL From 9b1d98496c8ef938f696d6462f038a907ccc8ae0 Mon Sep 17 00:00:00 2001 From: Eric Han <117511920+eh2077@users.noreply.github.com> Date: Tue, 16 May 2023 23:57:07 +0800 Subject: [PATCH 3/6] Update __tests__/Str-test.js Co-authored-by: Fedi Rajhi --- __tests__/Str-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/__tests__/Str-test.js b/__tests__/Str-test.js index d08fbffe..3b59f7c2 100644 --- a/__tests__/Str-test.js +++ b/__tests__/Str-test.js @@ -86,7 +86,7 @@ describe('Str.isValidMention', () => { }); describe('Str.normalizeWebsiteOfUrl', () => { - it('Normalize website of url to lower case and add missing https:// protocol', () => { + it('Normalize domain name to lower case and add missing https:// protocol', () => { expect(Str.normalizeWebsiteOfUrl('https://google.com')).toBe('https://google.com'); expect(Str.normalizeWebsiteOfUrl('google.com')).toBe('https://google.com'); expect(Str.normalizeWebsiteOfUrl('Https://google.com')).toBe('https://google.com'); From 29a562e280ad6fd68123d00ee2f0b6dcc0a73935 Mon Sep 17 00:00:00 2001 From: Eric Han <117511920+eh2077@users.noreply.github.com> Date: Tue, 16 May 2023 23:57:44 +0800 Subject: [PATCH 4/6] Update lib/str.js Co-authored-by: Fedi Rajhi --- lib/str.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/str.js b/lib/str.js index 6f22b1a4..ea0f0ba6 100644 --- a/lib/str.js +++ b/lib/str.js @@ -1028,7 +1028,7 @@ const Str = { * @param {url} url The URL to be formatted * @returns {String} The formatted URL */ - normalizeWebsiteOfUrl(url) { + normalizeURL(url) { const regex = new RegExp(`^${URL_REGEX}$`, 'i'); const match = regex.exec(url); if (!match) { From 9be3f94ead8d61a447012e17291246ad80b0c75f Mon Sep 17 00:00:00 2001 From: Eric Han Date: Wed, 17 May 2023 00:01:52 +0800 Subject: [PATCH 5/6] improve method name and remove outdated comments --- __tests__/Str-test.js | 16 ++++++++-------- lib/ExpensiMark.js | 8 ++------ lib/str.js | 2 +- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/__tests__/Str-test.js b/__tests__/Str-test.js index 3b59f7c2..a8d92a2a 100644 --- a/__tests__/Str-test.js +++ b/__tests__/Str-test.js @@ -85,14 +85,14 @@ describe('Str.isValidMention', () => { }); }); -describe('Str.normalizeWebsiteOfUrl', () => { +describe('Str.sanitizeURL', () => { it('Normalize domain name to lower case and add missing https:// protocol', () => { - expect(Str.normalizeWebsiteOfUrl('https://google.com')).toBe('https://google.com'); - expect(Str.normalizeWebsiteOfUrl('google.com')).toBe('https://google.com'); - expect(Str.normalizeWebsiteOfUrl('Https://google.com')).toBe('https://google.com'); - expect(Str.normalizeWebsiteOfUrl('https://GOOgle.com')).toBe('https://google.com'); - expect(Str.normalizeWebsiteOfUrl('FOO.com/blah_BLAH')).toBe('https://foo.com/blah_BLAH'); - expect(Str.normalizeWebsiteOfUrl('http://FOO.com/blah_BLAH')).toBe('http://foo.com/blah_BLAH'); - expect(Str.normalizeWebsiteOfUrl('HTtp://FOO.com/blah_BLAH')).toBe('http://foo.com/blah_BLAH'); + expect(Str.sanitizeURL('https://google.com')).toBe('https://google.com'); + expect(Str.sanitizeURL('google.com')).toBe('https://google.com'); + expect(Str.sanitizeURL('Https://google.com')).toBe('https://google.com'); + expect(Str.sanitizeURL('https://GOOgle.com')).toBe('https://google.com'); + expect(Str.sanitizeURL('FOO.com/blah_BLAH')).toBe('https://foo.com/blah_BLAH'); + expect(Str.sanitizeURL('http://FOO.com/blah_BLAH')).toBe('http://foo.com/blah_BLAH'); + expect(Str.sanitizeURL('HTtp://FOO.com/blah_BLAH')).toBe('http://foo.com/blah_BLAH'); }); }); diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index 98bd6133..84230c0e 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -113,13 +113,11 @@ export default class ExpensiMark { return this.modifyTextForUrlLinks(regex, textToProcess, replacement); }, - // We use a function here to check if there is already a https:// on the link. - // If there is not, we force the link to be absolute by prepending '//' to the target. replacement: (match, g1, g2) => { if (g1.match(CONST.REG_EXP.EMOJIS) || !g1.trim()) { return match; } - return `${g1.trim()}`; + return `${g1.trim()}`; }, }, @@ -152,10 +150,8 @@ export default class ExpensiMark { return this.modifyTextForUrlLinks(regex, textToProcess, replacement); }, - // We use a function here to check if there is already a https:// on the link. - // If there is not, we force the link to be absolute by prepending '//' to the target. replacement: (match, g1, g2) => { - const href = Str.normalizeWebsiteOfUrl(g2); + const href = Str.sanitizeURL(g2); return `${g1}${g2}${g1}`; }, }, diff --git a/lib/str.js b/lib/str.js index ea0f0ba6..27192f28 100644 --- a/lib/str.js +++ b/lib/str.js @@ -1028,7 +1028,7 @@ const Str = { * @param {url} url The URL to be formatted * @returns {String} The formatted URL */ - normalizeURL(url) { + sanitizeURL(url) { const regex = new RegExp(`^${URL_REGEX}$`, 'i'); const match = regex.exec(url); if (!match) { From 58224a6c1cc29ac54b8f009fa6e2057e40d0d850 Mon Sep 17 00:00:00 2001 From: Eric Han <117511920+eh2077@users.noreply.github.com> Date: Wed, 17 May 2023 20:29:06 +0800 Subject: [PATCH 6/6] Update lib/str.js Co-authored-by: Maria D'Costa --- lib/str.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/str.js b/lib/str.js index 27192f28..da76d7ef 100644 --- a/lib/str.js +++ b/lib/str.js @@ -1023,7 +1023,7 @@ const Str = { }, /** - * * Formats a URL by converting the domain name to lowercase and adding the missing 'https://' protocol. + * Formats a URL by converting the domain name to lowercase and adding the missing 'https://' protocol. * * @param {url} url The URL to be formatted * @returns {String} The formatted URL