首先,www.domain.com
不是 URL,而是主机名,并且
<a href="www.domain.com">
不会工作 — 它会寻找一个.com
文件名为www.domain
相对于当前页面。
在一般情况下不可能突出显示主机名,因为几乎任何东西都可以是主机名。你could尝试突出显示“www.something.dot.separated.words”,但它并不是那么可靠,并且有许多网站不使用www.
主机名前缀。我会尽力避免这种情况。
/\bhttps?:\/\/[^\s<>"`{}|\^\[\]\\]+/;
这是一个非常自由的模式,您可以将其用作检测 HTTP URL 的起点。根据您拥有的输入类型,您可能希望缩小其允许的范围,并且可能值得检测尾随字符,例如.
or !
这可能是 URL 的有效部分,但实际上通常不是。
(你可以使用|
允许either网址语法or the www.hostname
语法,如果你喜欢的话。)
无论如何,一旦您确定了首选模式,您就需要在页面上的文本节点中找到该模式。不要运行正则表达式innerHTML
markup.如果你试图标记每一个,你最终会完全毁掉这个页面。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]);
}
}
}