将文字转换为<a> tags only</a>之外的链接

时间:2014-04-22 19:10:10

标签: javascript jquery html

这是我的问题。我创建了一个函数来解析javascript中的链接,但我坚持使用的用例是在带有链接的帖子中可能已经有HTML。

用户无法发布真正的HTML,但主持人和管理员可以,这意味着我需要处理这两种情况。

以下是典型用户发布HTML的示例:

<div class="teaser">
    This is just your normal post http://google.com some other stuff
</div>

管理员/主持人:

<div class="teaser">
    <b>
        <a href="http://test.com/who.html" target="_blank">THIS LINK</a>
    </b>
    <a href="http://test.com/who.html" target="_blank"><br></a><br>
    Supplemental reading: <a href="http://test.com/who.html" target="_blank">Link again</a>
</div>

通常情况下,我会使用类似

的内容
function replaceURLWithHTMLLinks(text) {
    var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
    return text.replace(exp,"<a href='$1' target='_blank'>$1</a>"); 
}

c.not('a').each(function() {
    var html = $(this).html();
    $(this).html(replaceURLWithHTMLLinks(html));
});

但是这会导致解析存在于href属性内部的链接。我需要能够仅在标签之外创建链接,并且需要通过所有孩子,因为您注意到这是mod / admin帖子中的第一个孩子(如果他们这样选择的话)。 / p>

Mods和管理员基本上可以在他们的帖子中放置他们想要的任何HTML,因此标签可以在帖子层次结构中的任何位置都不一致。

我可能无法解析管理员或mod帖子上的链接,但有时一些mod和管理员使用正确的HTML标签,有时他们不会,这就是为什么我想知道正确的方法这样做。

2 个答案:

答案 0 :(得分:0)

试试这个:

var exp = /^(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
$('.teaser').each(function() {
    var i, words;
    $this = $(this);
    words = $this.html().split(' ');
    for (i = 0; i < words.length; i++) {
        if (exp.test(words[i])) {
            words[i] = words[i].replace(exp, "<a href='$1' target='_blank'>$1</a>");
        }
    }
    $this.html(words.join(' '));
});

<强> Demo Link

答案 1 :(得分:0)

我似乎找到了答案here

    filterTeaserLinkContent: function(data) {
        var exp = /\b((https?|ftps?|about|bitcoin|git|irc[s6]?):(\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/|magnet:\?(dn|x[lts]|as|kt|mt|tr)=)([^\s()<>]+|\([^\s()<>]+\))+(\([^\s()<>]+\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])/g;

        var nodes = data[0].childNodes;

        for(var i = 0; i < nodes.length; i++) {
            var n = nodes[i];

            if(n.nodeType == n.TEXT_NODE || n.nodeName == 'BR') {
                var g = n.textContent.match(exp);

                while(g) {
                    var idx=n.textContent.indexOf(g[0]);
                    var pre=n.textContent.substring(0,idx);
                    var a=document.createElement("a");

                    if (!/^[a-z][\w-]+:/.test(g[0])) {
                        a.href = "http://" + g[0];
                    } else {
                        a.href = g[0];
                    }

                    a.innerText = g[0];
                    n.textContent = n.textContent.substring(idx+g[0].length);
                    n.parentElement.insertBefore(a,n);
                    g=n.textContent.match(exp);
                }
            } else {
                Board.filterTeaserLinkContent($(n));
            }
        }
    },

    filterTeaserContent: function(data) {
        // Jam into <div> so we can play with it
        var c = $('<div>' + data + '</div>');

        // Remove <wbr> tag which breaks links
        c.find('wbr').each(function() {
            $(this).remove();
        });

        // Re-parse the HTML after removing <wbr> or else the text nodes won't be joined
        c = $('<div>' + c.html() + '</div>');

        // I actually forget what this does, but fuck it. Shit.
        c.not("div, s, span, a").each(function() {
            var content = $(this).contents();
            $(this).replaceWith(content);
        });

        Board.filterTeaserLinkContent(c);

        // Remove images in post preview because they don't need to be here...
        c.find('img').each(function() {
            $(this).remove();
        });

        // Simplify line breaks
        return c.html().replace(/<br ?\/?><br ?\/?>/g, "<br>");
    },

如果有人好奇,可以在4chan API中使用。