替换URL(带链接)但在已定义某些链接的文本中

时间:2013-01-04 17:55:46

标签: javascript html regex url hyperlink

我在此链接中查看了基本问题的答案:How to replace plain URLs with links?并决定使用Christian Koch建议的代码,但它只是部分涵盖了我需要做的事情。我希望有人可以帮助我。

Christian Koch提供的代码很好用,有一个例外 - 当我的文本已经包含链接和纯文本时,这些链接会得到一个双'a'标记,因此导致html问题导致文本无法正确显示浏览器。

例如,代码可以正常工作:

     www.yahoo.com is a website just like http://www.google.com

我看到雅虎和谷歌文本现在显示为链接,并且两者都有一个链接包装,就像我期望的那样:

     <a href="http://www.yahoo.com">www.yahoo.com</a> is a website just like <a href="http://www.google.com">http://www.google.com</a>

现在接受此文本(包含基本文本和已定义的链接):

     www.yahoo.com is a website just like <a href="http://www.google.com">http://www.google.com</a>

使用提供的代码时,雅虎链接是正确的,但谷歌链接现在有一个双重标记:

     <a href="http://www.yahoo.com">www.yahoo.com</a> is a website just like <a href="<a href="http://www.google.com">http://www.google.com</a>" target="_blank"><a href="http://www.google.com">http://www.google.com</a></a>

有人可以帮我修改模式,这样当文本已包含链接时,模式会忽略它,但仍会替换没有标记的其他文本。当且仅当文本尚未包含在链接标记中时,我才希望模式进行替换。

以下是我在其他帖子中使用的代码:

   doLinks: function(originalText) 
   {
    // http://, https://, ftp://
    var urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;

    // www. sans http:// or https://
    var pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim;

    // Email addresses *** here I've changed the expression ***
    var emailAddressPattern = /(([a-zA-Z0-9_\-\.]+)@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6}))+/gim;

    return originalText
        .replace(urlPattern, '<a target="_blank" href="$&">$&</a>')
        .replace(pseudoUrlPattern, '$1<a target="_blank" href="http://$2">$2</a>')
        .replace(emailAddressPattern, '<a target="_blank" href="mailto:$1">$1</a>');
}

2 个答案:

答案 0 :(得分:2)

在问题再看一遍之后,我开始相信几个子模式的组合会比一个超级模式做得更好。所以我将pseudoUrlPattern划分为两个,一个用于行开头的url,另一个用于给定文本中的每个其他url。 请考虑以下修订代码,并附上我的测试文本:

  var doLinks = function(originalText) {

        var urlPattern = /[^<>]\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|](?![^<>])/gim;

        var pseudoUrlPattern1 = /^([^\/])?(www\.[\S]+(\b|$|[^<>]))/gim
        var pseudoUrlPattern2 = /([^\/"><])(www\.[\S]+(\b|$))(?![^<>])?/gim;

        var emailAddressPattern = /(([a-zA-Z0-9_\-\.]+)@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6}))+/gim;

        return originalText
            .replace(urlPattern, '<a target="_blank" href="$&">$&</a>')
            .replace(pseudoUrlPattern1, '$1<a target="_blank" href="http://$2">$2</a>')
            .replace(pseudoUrlPattern2, '$1<a target="_blank" href="http://$2">$2</a>')
            .replace(emailAddressPattern, '<a target="_blank" href="mailto:$1">$1</a>');
    }    

    var string = 'www.yahoo.com is a website just like <a href="http://www.google.com">http://www.google.com</a> and not like <a href="www.facebook.com "> www.facebook.com </a> and not like www.example.com';
试一试,告诉我它是怎么回事。

要注意的一件事:已经在锚标签中的网址最好不要在网址和标记之间留有任何空格。

答案 1 :(得分:1)

当网址为引号'或双引号"时,请禁止替换。

// http://, https://, ftp://
var urlPattern = /[^"']\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;

// www. sans http:// or https://
var pseudoUrlPattern = /(^|[^\/"'])(www\.[\S]+(\b|$))/gim;

// Email addresses *** here I've changed the expression ***
var emailAddressPattern = /[^"'](([a-zA-Z0-9_\-\.]+)@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6}))+/gim;

也许您需要转义引号或双引号。我没有测试它。

顺便说一句:你的正则表达式与所有域名都不匹配。有越来越多的国际化域名。请参阅此处的示例in the German Wikipedia