如何从文本输入向URL添加锚标记

时间:2009-12-24 17:09:17

标签: php javascript jquery html

我希望能够在注释字段中输入用户输入的文本并检查URL类型表达式,如果存在,则在显示注释时添加锚标记(到url)。

我在服务器端使用PHP,在客户端使用Javascript(使用jQuery),所以我应该等到它显示之前检查URL吗?或者在将锚标记插入数据库之前添加它?

所以

<textarea id="comment">check out blahblah.com or www.thisthing.co.uk or http://checkthis.us/</textarea>  

成为

<div id="commentDisplay">check out <a href="blahblah.com">blahblah.com</a> or <a href="www.thisthing.co.uk">www.thisthing.co.uk</a> or <a href="http://checkthis.us/">http://checkthis.us/</a></div>

8 个答案:

答案 0 :(得分:22)

首先是请求。在将数据写入数据库之前不要这样做。相反,在向最终用户显示数据之前执行此操作。这将减少所有混乱,并将在未来为您提供更大的灵活性。

一个示例found online如下:

$text = preg_replace('@(https?://([-\w\.]+)+(:\d+)?(/([-\w/_\.]*(\?\S+)?)?)?)@', '<a href="$1">$1</a>', $text);

来自daringfireball.net的更彻底的一个:

/**
 * Replace links in text with html links
 *
 * @param  string $text
 * @return string
 */
function auto_link_text($text)
{
   $pattern  = '#\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))#';
   $callback = create_function('$matches', '
       $url       = array_shift($matches);
       $url_parts = parse_url($url);

       $text = parse_url($url, PHP_URL_HOST) . parse_url($url, PHP_URL_PATH);
       $text = preg_replace("/^www./", "", $text);

       $last = -(strlen(strrchr($text, "/"))) + 1;
       if ($last < 0) {
           $text = substr($text, 0, $last) . "&hellip;";
       }

       return sprintf(\'<a rel="nowfollow" href="%s">%s</a>\', $url, $text);
   ');

   return preg_replace_callback($pattern, $callback, $text);
}

答案 1 :(得分:13)

我改编了Jonathan Sampson的正则表达式选项,以便它对什么是域名更加宽容(不需要http(s)来限定)。

function hyperlinksAnchored($text) {
    return preg_replace('@(http)?(s)?(://)?(([-\w]+\.)+([^\s]+)+[^,.\s])@', '<a href="http$2://$4">$1$2$3$4</a>', $text);
}

适用于这些网址(并成功地省略了尾随句号或逗号):

http://www.google.com/
https://www.google.com/.
www.google.com
www.google.com.
www.google.com/test
google.com
google.com,
google.com/test
123.com/test
www.123.com.au
ex-ample.com
http://ex-ample.com
http://ex-ample.com/test-url_chars.php?param1=val1.
http://ex-ample.com/test-url_chars?param1=value1&param2=val+with%20spaces

希望能有所帮助。

答案 2 :(得分:3)

这是我的代码,用于格式化文本中的所有链接,包括电子邮件,有和没有协议的网址。

public function formatLinksInText($text)
{
    //Catch all links with protocol      
    $reg = '/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,}(\/\S*)?/'; 
    $formatText = preg_replace($reg, '<a href="$0" style="font-weight: normal;" target="_blank" title="$0">$0</a>', $formatText);

    //Catch all links without protocol
    $reg2 = '/(?<=\s|\A)([0-9a-zA-Z\-\.]+\.[a-zA-Z0-9\/]{2,})(?=\s|$|\,|\.)/';
    $formatText = preg_replace($reg2, '<a href="//$0" style="font-weight: normal;" target="_blank" title="$0">$0</a>', $formatText);

    //Catch all emails
    $emailRegex = '/(\S+\@\S+\.\S+)/';
    $formatText = preg_replace($emailRegex, '<a href="mailto:$1" style="font-weight: normal;" target="_blank" title="$1">$1</a>', $formatText);
    $formatText = nl2br($formatText);
    return $formatText;
}

答案 3 :(得分:2)

就个人而言,我会在展示之前用JS标记它,看起来比自己编辑用户评论更专业和可持续。

答案 4 :(得分:2)

改进Markd的答案,以避免小数,百分比,数字日期(10.3.2001),省略号和IP地址的链接:

    function addLinks($text) {
    return preg_replace('@(http)?(s)?(://)?(([a-zA-Z])([-\w]+\.)+([^\s\.]+[^\s]*)+[^,.\s])@', '<a target="ref" href="http$2://$4">$1$2$3$4</a>', $text);
}

适用于:

的http:// <强> www.google.com /
HTTPS:// <强> www.google.com /
。 的 www.google.com
www.google.com 即可。
www.google.com/test
google.com
google.com 下,
google.com/test
www.123.com.au
ex-ample.com
HTTP:// <强> ex-ample.com
HTTP:// <强> ex-ample.com/test-url_chars.php?param1=val1
。 http:// ex-ample.com/test-url_chars?param1=value1&param2=val+with%20spaces

不适用于:
<登记/> 123.com/test (没有'www'的数字域名)
保持流行观点的压力........保持平均值(省略号)
从379万(百分比和小数)增加3.8%至394万
Andrew Brooke编辑 - 07.08.2013 19:57 (dd.mm.yyyy日期)
10.1.1.1 (IP地址)

答案 5 :(得分:1)

我宁愿在服务器端这样做。 Javascript有“滞后”;它仅在整个HTML DOM树已加载并显示在Web浏览器中时运行。因此,在识别和解析URL之前可能需要(尽管很短)。客户端可能会在他仍然面对内容时看到链接立即被替换。这可能会导致“wtf?”在客户端的经验。现在这与广告/垃圾邮件/间谍软件太快相关。你应该尽可能地避免这种情况。不要使用JS来更改内容onload,而只是在用户控制的事件(onclick,onchange,onfocus等)中进行。在保存或显示之前,请使用服务器端语言更改内容。

因此,只需查找一个PHP脚本,该脚本解析文本(或使用正则表达式),以纯文本形式构建基于URL的完整链接。你可以找到很多here。祝你好运。

答案 6 :(得分:0)

只需在此处推荐一个有用的插件:External Links https://wordpress.org/plugins/sem-external-links/

答案 7 :(得分:0)

我对已接受的答案进行了一些更新,该答案也适用于没有协议的链接(没有 http(s):// 的链接) - 在它们被链接之前但作为无效的相对链接。

我还为文档添加了一些注释。

/**
 * Replace links in text with html links
 *
 * @param  string $text Text to add links to
 * @return string Text with links added
 */
function auto_link_text( $text )
{
    $pattern = "#\b((?:https?:(?:/{1,3}|[a-z0-9%])|[a-z0-9.\-]+[.](?:com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)/)(?:[^\s()<>{}\[\]]+|\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\))+(?:\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\)|[^\s`!()\[\]{};:'.,<>?«»“”‘’])|(?:(?<!@)[a-z0-9]+(?:[.\-][a-z0-9]+)*[.](?:com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)\b/?(?!@)))#";
    return preg_replace_callback( $pattern, function( $matches ) {
        $url = array_shift( $matches );

        // force http if no protocol included
        if ( !startsWith( $url, 'http' ) ) {
            $url = 'http://' . $url;
        }

        // make link text from url - removing protocol
        $text = parse_url( $url, PHP_URL_HOST ) . parse_url( $url, PHP_URL_PATH );
        
        // remove the www from the link text
        $text = preg_replace( "/^www./", "", $text );

        // remove any long trailing path from url
        $last = -( strlen( strrchr( $text, "/" ) ) ) + 1;
        if ( $last < 0 ) {
            $text = substr( $text, 0, $last ) . "&hellip;";
        }

        // update 
        return sprintf(
            '<a rel="nowfollow" target="_blank" href="%s">%s</a>', 
            $url, 
            $text
        );
    }, $text );
}

/**
 * Check strings for starting match
 *
 * @param  string $string String to check.
 * @param  string $startString Startin string to match.
 * @return boolean Wether string begins with startString. 
 */
function startsWith( $string, $startString ) 
{ 
    $len = strlen($startString); 
    return (substr($string, 0, $len) === $startString); 
}