Last active
December 13, 2019 15:03
-
-
Save anton-chernianu/757f7196a0f159288a2e64c1fb0ef23c to your computer and use it in GitHub Desktop.
JavaScript: Regex matching links without <a> and replace
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function addTagToLinks(str) { | |
const httpRegex = "((?:(http|https|Http|Https|rtsp|Rtsp):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)" | |
+ "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_" | |
+ "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?" | |
+ "((?:(?:[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}\\.)+" // named host | |
+ "(?:" // plus top level domain | |
+ "(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])" | |
+ "|(?:biz|b[abdefghijmnorstvwyz])" | |
+ "|(?:cat|com|coop|c[acdfghiklmnoruvxyz])" | |
+ "|d[ejkmoz]" | |
+ "|(?:edu|e[cegrstu])" | |
+ "|f[ijkmor]" | |
+ "|(?:gov|g[abdefghilmnpqrstuwy])" | |
+ "|h[kmnrtu]" | |
+ "|(?:info|int|i[delmnoqrst])" | |
+ "|(?:jobs|j[emop])" | |
+ "|k[eghimnrwyz]" | |
+ "|l[abcikrstuvy]" | |
+ "|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])" | |
+ "|(?:name|net|n[acefgilopruz])" | |
+ "|(?:org|om)" | |
+ "|(?:pro|p[aefghklmnrstwy])" | |
+ "|qa" | |
+ "|r[eouw]" | |
+ "|s[abcdeghijklmnortuvyz]" | |
+ "|(?:tel|travel|t[cdfghjklmnoprtvwz])" | |
+ "|u[agkmsyz]" | |
+ "|v[aceginu]" | |
+ "|w[fs]" | |
+ "|y[etu]" | |
+ "|z[amw]))" | |
+ "|(?:(?:25[0-5]|2[0-4]" // or ip address | |
+ "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(?:25[0-5]|2[0-4][0-9]" | |
+ "|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1]" | |
+ "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}" | |
+ "|[1-9][0-9]|[0-9])))" | |
+ "(?:\\:\\d{1,5})?)" // plus option port number | |
+ "(\\/(?:(?:[a-zA-Z0-9\\;\\/\\?\\:\\@\\&\\=\\#\\~" // plus option query params | |
+ "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?" | |
+ "(?:\\b|$)"; | |
// выбираем ссылки, которые не следуют за аттрибутом href или которые не находятся перед закрывающим тегом </a> | |
const regex = "((?<href><a\\s+href=\")?" + httpRegex + ")(?<tag>(?!.*<\\/a>))"; | |
let result = str.matchAll(new RegExp(regex, 'g')); | |
let strNew = str, | |
// каждая замена ссылки увеличивает длину оригинальной строки | |
// padding содержит кол-во символов, на которое увеличилась оригинальная строка после замены | |
padding = 0; | |
for (let item of result) { | |
// если ссылка находится после аттрибута href(группа href не undefined) | |
// или ссылка содержит закрывающий тег </a> | |
// то пропускаем эту ссылку | |
if (item.groups.href !== undefined || (item.groups.tag !== undefined && -1 !== item.groups.tag.indexOf('</a>'))) { | |
continue; | |
} | |
let insert = '<a href="' + item[0] + '">' + item[0] + "</a>", | |
startItemIndex = item.index + padding, | |
endItemIndex = startItemIndex + item[0].length; | |
strNew = strNew.slice(0, startItemIndex) + insert + strNew.slice(endItemIndex, strNew.length); | |
padding += (insert.length - item[0].length); | |
} | |
return strNew; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment