Во-первых, www.domain.com
- это не URL, это имя хоста, а
<a href="www.domain.com">
не будет работать - он будет искать .com
файл с именем www.domain
относительно текущей страницы.
Невозможно выделить имена хостов в общем случае, потому что имя хоста может быть почти любым. Вы могли бы попытаться выделить "www.something.dot.separated.words", но это не так уж и надежно, и есть много сайтов, которые не используют префикс www.
hostname. Я бы постарался избежать этого.
/\bhttps?:\/\/[^\s<>"`{}|\^\[\]\\]+/;
Это очень либеральный шаблон, который вы можете использовать в качестве отправной точки для обнаружения HTTP-URL. В зависимости от того, какой тип ввода у вас есть, вы можете захотеть сузить то, что он позволяет, и, возможно, стоит определить конечные символы, такие как .
или !
, которые были бы допустимыми частями URL, но на практике, как правило, нет т.
(Вы можете использовать |
, чтобы разрешить или синтаксис URL или www.hostname
синтаксис, если хотите.)
Так или иначе, как только вы остановитесь на предпочитаемом вами шаблоне, вам нужно будет найти этот шаблон в текстовых узлах на странице. Не запускайте регулярное выражение для innerHTML
разметки. В конечном итоге вы полностью испортите страницу, пытаясь разметить все href="http://something"
, которые уже находятся внутри разметки. Вы также уничтожите все существующие ссылки JavaScript, события или значения полей формы при замене содержимого innerHTML
.
В общем, регулярное выражение просто не может обработать HTML надежным способом. Воспользуйтесь тем фактом, что браузер уже проанализировал HTML на элементы и текстовые узлы, и просто посмотрите на текстовые узлы. Вам также следует избегать заглядывания внутрь элементов <a>
, поскольку разметка URL-адреса как ссылки, если она уже есть в ссылке, является глупой (и недействительной).
// Mark up `http://...` text in an element and its descendants as links.
//
function addLinks(element) {
var urlpattern= /\bhttps?:\/\/[^\s<>"`{}|\^\[\]\\]+/g;
findTextExceptInLinks(element, urlpattern, function(node, match) {
node.splitText(match.index+match[0].length);
var a= document.createElement('a');
a.href= match[0];
a.appendChild(node.splitText(match.index));
node.parentNode.insertBefore(a, node.nextSibling);
});
}
// Find text in descendents of an element, in reverse document order
// pattern must be a regexp with global flag
//
function findTextExceptInLinks(element, pattern, callback) {
for (var childi= element.childNodes.length; childi-->0;) {
var child= element.childNodes[childi];
if (child.nodeType===Node.ELEMENT_NODE) {
if (child.tagName.toLowerCase()!=='a')
findTextExceptInLinks(child, pattern, callback);
} else if (child.nodeType===Node.TEXT_NODE) {
var matches= [];
var match;
while (match= pattern.exec(child.data))
matches.push(match);
for (var i= matches.length; i-->0;)
callback.call(window, child, matches[i]);
}
}
}