From 34550223aac14e32d4feae0ca48bc64effcbc285 Mon Sep 17 00:00:00 2001 From: Deependra Solanki Date: Thu, 23 Nov 2023 11:33:10 +0530 Subject: [PATCH] [FIX] web_editor: fix url regex when containing symbols MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit [1] introduces a stronger regex for url containing symbols. It did so by using a negative lookbehind, which was not supported on some version of Safari iOS and edge. Later commit [2] was introduced in attempt to reproduce the same behaviour without using negative lookbehind but missed some cases such as github compare link where the url had multiple symbols. This commit is an attempt to reproduce the same behaviour like [1] while improving [2]. [1]: a42a19e [2]: ff99e45 task-3468646 closes odoo/odoo#143250 Signed-off-by: Geelen Sébastien (sge) --- .../js/editor/odoo-editor/src/utils/utils.js | 2 +- .../editor/odoo-editor/test/spec/link.test.js | 43 +++++++++++++++++++ .../odoo-editor/test/spec/urlRegex.test.js | 12 ++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/addons/web_editor/static/src/js/editor/odoo-editor/src/utils/utils.js b/addons/web_editor/static/src/js/editor/odoo-editor/src/utils/utils.js index f4b9626cee5..b7e6a8c7c0c 100644 --- a/addons/web_editor/static/src/js/editor/odoo-editor/src/utils/utils.js +++ b/addons/web_editor/static/src/js/editor/odoo-editor/src/utils/utils.js @@ -50,7 +50,7 @@ const tldWhitelist = [ 'ug', 'uk', 'um', 'us', 'uy', 'uz', 'va', 'vc', 've', 'vg', 'vi', 'vn', 'vu', 'wf', 'ws', 'ye', 'yt', 'yu', 'za', 'zm', 'zr', 'zw', 'co\\.uk']; -const urlRegexBase = `|(?:www.))[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-zA-Z][a-zA-Z0-9]{1,62}|(?:[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.(?:${tldWhitelist.join('|')})\\b))(?:\\/[^\\s.,'")}\\]]*[?#.,)}\\]'"]?[^\\s.,'")}\\]]+|(?:[^!(){}.,\\[\\]'"\\s]+)|\\/[^\\s.,'")}\\]]*[^\\s?#.,'")}\\]]*)?`; +const urlRegexBase = `|(?:www.))[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-zA-Z][a-zA-Z0-9]{1,62}|(?:[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.(?:${tldWhitelist.join('|')})\\b))(?:(?:[/?#])[^\\s]*[^!.,})\\]'"\\s]|(?:[^!(){}.,[\\]'"\\s]+))?`; const httpCapturedRegex= `(https?:\\/\\/)`; export const URL_REGEX = new RegExp(`((?:(?:${httpCapturedRegex}${urlRegexBase})`, 'i'); diff --git a/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/link.test.js b/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/link.test.js index 257ff164f2b..cc083316086 100644 --- a/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/link.test.js +++ b/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/link.test.js @@ -48,6 +48,7 @@ describe('Link', () => { testUrlRegex('google.com!', {expectedUrl: 'google.com'}); testUrlRegex('google.com)', {expectedUrl: 'google.com'}); testUrlRegex('google.com(', {expectedUrl: 'google.com'}); + testUrlRegex('google.com/ a', {expectedUrl: 'google.com/'}); testUrlRegex('google.com. a', {expectedUrl: 'google.com'}); testUrlRegex('google.com, a', {expectedUrl: 'google.com'}); @@ -59,6 +60,20 @@ describe('Link', () => { testUrlRegex('google.com/}', {expectedUrl: 'google.com/'}); testUrlRegex("google.com/'", {expectedUrl: 'google.com/'}); testUrlRegex('google.com/"', {expectedUrl: 'google.com/'}); + testUrlRegex('google.com#.', {expectedUrl: 'google.com#'}); + testUrlRegex('google.com#,', {expectedUrl: 'google.com#'}); + testUrlRegex('google.com#)', {expectedUrl: 'google.com#'}); + testUrlRegex('google.com#]', {expectedUrl: 'google.com#'}); + testUrlRegex('google.com#}', {expectedUrl: 'google.com#'}); + testUrlRegex("google.com#'", {expectedUrl: 'google.com#'}); + testUrlRegex('google.com#"', {expectedUrl: 'google.com#'}); + testUrlRegex('google.com?,', {expectedUrl: 'google.com?'}); + testUrlRegex('google.com?.', {expectedUrl: 'google.com?'}); + testUrlRegex('google.com?)', {expectedUrl: 'google.com?'}); + testUrlRegex('google.com?]', {expectedUrl: 'google.com?'}); + testUrlRegex('google.com?}', {expectedUrl: 'google.com?'}); + testUrlRegex("google.com?'", {expectedUrl: 'google.com?'}); + testUrlRegex('google.com?"', {expectedUrl: 'google.com?'}); // The previous special character should be included when they are nt at the end. testUrlRegex('google.com/.a', {expectedUrl: 'google.com/.a'}); @@ -73,20 +88,33 @@ describe('Link', () => { testUrlRegex('google.com/(', {expectedUrl: 'google.com/('}); testUrlRegex('google.com/[', {expectedUrl: 'google.com/['}); testUrlRegex('google.com/{', {expectedUrl: 'google.com/{'}); + testUrlRegex('google.com?(', {expectedUrl: 'google.com?('}); + testUrlRegex('google.com?[', {expectedUrl: 'google.com?['}); + testUrlRegex('google.com?{', {expectedUrl: 'google.com?{'}); + testUrlRegex('google.com#(', {expectedUrl: 'google.com#('}); + testUrlRegex('google.com#[', {expectedUrl: 'google.com#['}); + testUrlRegex('google.com#{', {expectedUrl: 'google.com#{'}); testUrlRegex('google.co.uk'); + testUrlRegex('google123.com'); testUrlRegex('http://google.com'); + testUrlRegex('http://google123.com'); testUrlRegex('https://google.com'); + testUrlRegex('https://google123.com'); testUrlRegex('https://www.google.com'); testUrlRegex('https://google.shop'); testNotUrlRegex('google.shop'); testUrlRegex('google.com/'); + testUrlRegex('google.com/path/123/abc/4'); testUrlRegex('http://google.com/'); + testUrlRegex('http://google.com/home'); + testUrlRegex('http://google.com/home/'); testUrlRegex('https://google.com/'); testUrlRegex('https://google.co.uk/'); testUrlRegex('https://www.google.com/'); testNotUrlRegex('google.shop/'); testUrlRegex('http://google.com/foo#test'); + testUrlRegex('http://google.com/#test'); testNotUrlRegex('a.bcd.ef'); testUrlRegex('a.bc.de'); testNotUrlRegex('a.bc.d'); @@ -98,11 +126,26 @@ describe('Link', () => { testUrlRegex('google.com?data=hello', { expectedUrl: 'google.com?data=hello' }); testUrlRegex('google.com/?data=hello', { expectedUrl: 'google.com/?data=hello' }); testUrlRegex('google.com/foo/?data=hello', { expectedUrl: 'google.com/foo/?data=hello' }); + testUrlRegex('google.com/foo/?data1=hello1&data2=hello2', { expectedUrl: 'google.com/foo/?data1=hello1&data2=hello2' }); testUrlRegex('google.com/.?data=hello', { expectedUrl: 'google.com/.?data=hello' }); testUrlRegex('google.com?data=hello#anchor', { expectedUrl: 'google.com?data=hello#anchor' }); testUrlRegex('google.com/?data=hello#anchor', { expectedUrl: 'google.com/?data=hello#anchor' }); testUrlRegex('google.com/.?data=hello#anchor', { expectedUrl: 'google.com/.?data=hello#anchor' }); testUrlRegex('google.com/foo/?data=hello&data2=foo#anchor', { expectedUrl: 'google.com/foo/?data=hello&data2=foo#anchor' }); + + // Url containing some special characters + testUrlRegex('www.google.com/path/1-2-3', { expectedUrl: 'www.google.com/path/1-2-3' }); + testUrlRegex('https://google.com/abc..def', { expectedUrl: 'https://google.com/abc..def' }); + testUrlRegex('https://google.com/a/b+c@d', { expectedUrl: 'https://google.com/a/b+c@d' }); + testUrlRegex('sub.example-website.com', { expectedUrl: 'sub.example-website.com' }); + testUrlRegex('http://sub.example-website.com', { expectedUrl: 'http://sub.example-website.com' }); + testUrlRegex('http://user:password@example.com', { expectedUrl: 'http://user:password@example.com' }); + testUrlRegex('http://google.com/a_b', { expectedUrl: 'http://google.com/a_b' }); + testUrlRegex('https://google.com?query=ab.cd', { expectedUrl: 'https://google.com?query=ab.cd' }); + testUrlRegex(`google.com/'ab'/cd`, { expectedUrl: "google.com/'ab'/cd" }); + testUrlRegex(`www.google.com/a!b/c?d,e,f#g!i`, { expectedUrl: 'www.google.com/a!b/c?d,e,f#g!i' }); + testUrlRegex(`www.google.com/a%b%c`, { expectedUrl: 'www.google.com/a%b%c' }); + testUrlRegex(`http://google.com?a.b.c&d!e#e'f`, { expectedUrl: "http://google.com?a.b.c&d!e#e'f" }); }); describe('insert Link', () => { describe('range collapsed', () => { diff --git a/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/urlRegex.test.js b/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/urlRegex.test.js index f812e87013c..2a6ca839179 100644 --- a/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/urlRegex.test.js +++ b/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/urlRegex.test.js @@ -21,6 +21,18 @@ describe('urlRegex', () => { const match = text.match(URL_REGEX); chai.expect(match[0]).to.be.equal(url); }); + it('should match abc.abc.com', () => { + const url = 'abc.abc.com'; + const text = `abc ${url} abc`; + const match = text.match(URL_REGEX); + chai.expect(match[0]).to.be.equal(url); + }); + it('should not match abc.abc.abc', () => { + const url = 'abc.abc.abc'; + const text = `abc ${url} abc`; + const match = text.match(URL_REGEX); + chai.expect(match).to.be.equal(null); + }); it('should match http://abc.abc.abc', () => { const url = 'http://abc.abc.abc'; const text = `abc ${url} abc`;