diff --git a/client/js/libs/handlebars/ircmessageparser/findLinks.js b/client/js/libs/handlebars/ircmessageparser/findLinks.js new file mode 100644 index 00000000..031afa17 --- /dev/null +++ b/client/js/libs/handlebars/ircmessageparser/findLinks.js @@ -0,0 +1,53 @@ +"use strict"; + +const URI = require("urijs"); + +const commonSchemes = [ + "http", "https", + "ftp", "sftp", + "smb", "file", + "irc", "ircs", + "svn", "git", + "steam", "mumble", "ts3server", + "svn+ssh", "ssh", +]; + +function findLinks(text) { + let result = []; + let lastPosition = 0; + + URI.withinString(text, function(url, start, end) { + // v-- fix: url was modified and does not match input string -> cant be mapped + if (text.indexOf(url, lastPosition) < 0) { + return; + } + // ^-- /fix: url was modified and does not match input string -> cant be mapped + + // v-- fix: use prefered scheme + const parsed = URI(url); + const parsedScheme = parsed.scheme().toLowerCase(); + const matchedScheme = commonSchemes.find(scheme => parsedScheme.endsWith(scheme)); + + if (matchedScheme) { + const prefix = parsedScheme.length - matchedScheme.length; + start += prefix; + url = url.slice(prefix); + } + // ^-- /fix: use prefered scheme + + // URL matched, but does not start with a protocol, add it + if (!parsedScheme.length) { + url = "http://" + url; + } + + result.push({ + start: start, + end: end, + link: url + }); + }); + + return result; +} + +module.exports = findLinks; diff --git a/client/js/libs/handlebars/parse.js b/client/js/libs/handlebars/parse.js index 8c6ae432..fa21b898 100644 --- a/client/js/libs/handlebars/parse.js +++ b/client/js/libs/handlebars/parse.js @@ -1,59 +1,11 @@ "use strict"; const Handlebars = require("handlebars/runtime"); -const URI = require("urijs"); const parseStyle = require("./ircmessageparser/parseStyle"); const findChannels = require("./ircmessageparser/findChannels"); +const findLinks = require("./ircmessageparser/findLinks"); const merge = require("./ircmessageparser/merge"); -const commonSchemes = [ - "http", "https", - "ftp", "sftp", - "smb", "file", - "irc", "ircs", - "svn", "git", - "steam", "mumble", "ts3server", - "svn+ssh", "ssh", -]; - -function findLinks(text) { - let result = []; - let lastPosition = 0; - - URI.withinString(text, function(url, start, end) { - // v-- fix: url was modified and does not match input string -> cant be mapped - if (text.indexOf(url, lastPosition) < 0) { - return; - } - // ^-- /fix: url was modified and does not match input string -> cant be mapped - - // v-- fix: use prefered scheme - const parsed = URI(url); - const parsedScheme = parsed.scheme().toLowerCase(); - const matchedScheme = commonSchemes.find(scheme => parsedScheme.endsWith(scheme)); - - if (matchedScheme) { - const prefix = parsedScheme.length - matchedScheme.length; - start += prefix; - url = url.slice(prefix); - } - // ^-- /fix: use prefered scheme - - // URL matched, but does not start with a protocol, add it - if (!parsedScheme.length) { - url = "http://" + url; - } - - result.push({ - start: start, - end: end, - link: url - }); - }); - - return result; -} - function createFragment(fragment) { let className = ""; if (fragment.bold) { diff --git a/test/client/js/libs/handlebars/ircmessageparser/findLinks.js b/test/client/js/libs/handlebars/ircmessageparser/findLinks.js new file mode 100644 index 00000000..f3f228f2 --- /dev/null +++ b/test/client/js/libs/handlebars/ircmessageparser/findLinks.js @@ -0,0 +1,106 @@ +"use strict"; + +const expect = require("chai").expect; +const findLinks = require("../../../../../../client/js/libs/handlebars/ircmessageparser/findLinks"); + +describe("findLinks", () => { + it("should find url", () => { + const input = "irc://freenode.net/thelounge"; + const expected = [{ + start: 0, + end: 28, + link: "irc://freenode.net/thelounge", + }]; + + const actual = findLinks(input); + + expect(actual).to.deep.equal(expected); + }); + + it("should find urls with www", () => { + const input = "www.nooooooooooooooo.com"; + const expected = [{ + start: 0, + end: 24, + link: "http://www.nooooooooooooooo.com" + }]; + + const actual = findLinks(input); + + expect(actual).to.deep.equal(expected); + }); + + it("should find urls in strings", () => { + const input = "look at https://thelounge.github.io/ for more information"; + const expected = [{ + link: "https://thelounge.github.io/", + start: 8, + end: 36 + }]; + + const actual = findLinks(input); + + expect(actual).to.deep.equal(expected); + }); + + it("should find urls in strings starting with www", () => { + const input = "use www.duckduckgo.com for privacy reasons"; + const expected = [{ + link: "http://www.duckduckgo.com", + start: 4, + end: 22 + }]; + + const actual = findLinks(input); + + expect(actual).to.deep.equal(expected); + }); + + it("should find urls with odd surroundings", () => { + const input = ""; + const expected = [{ + link: "https://theos.kyriasis.com/~kyrias/stats/archlinux.html", + start: 1, + end: 56 + }]; + + const actual = findLinks(input); + + expect(actual).to.deep.equal(expected); + }); + + it("should find urls with starting with www. and odd surroundings", () => { + const input = ".:www.github.com:."; + const expected = [{ + link: "http://www.github.com", + start: 2, + end: 16 + }]; + + const actual = findLinks(input); + + expect(actual).to.deep.equal(expected); + }); + + it("should not find urls", () => { + const input = "text www. text"; + const expected = []; + + const actual = findLinks(input); + + expect(actual).to.deep.equal(expected); + }); + + it("should handle multiple www. correctly", () => { + const input = "www.www.test.com"; + const expected = [{ + link: "http://www.www.test.com", + start: 0, + end: 16 + }]; + + const actual = findLinks(input); + + expect(actual).to.deep.equal(expected); + }); +});