【问题标题】:How to add anchor tag to a URL from text input如何从文本输入将锚标记添加到 URL
【发布时间】:2010-12-29 20:47:04
【问题描述】:

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

我在服务器端使用 PHP,在客户端使用 Javascript(带有 jQ​​uery),所以我应该等到 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>

【问题讨论】:

  • 我了解您想要实现的目标,但由于您的示例在语法上无效,我只是警告您:您需要使用 protocol 指定外部 URL (http://),否则它们将变为相对并指向您自己的域!因此,http://blahblah.com 等等。
  • 如果您在将评论插入数据库之前进行这种操作,如果有人想编辑他的帖子,您就会遇到问题:中间会有一些 HTML ;;因此,要么在显示时进行该操作,要么在数据库中存储 2 个版本的评论(一个“干净”,一个“转换/丰富”)
  • @BalusC 你是对的,我是想在显示中更改它,但我很高兴复制粘贴并忘记了。

标签: php javascript jquery html


【解决方案1】:

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

一个例子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);
}

【讨论】:

  • 这会起作用,虽然我担心可能会出现延迟(它会一次显示很多 cmets)
  • 试一试。我怀疑你会遇到任何明显的滞后。
  • 真的很简洁(第二个功能)
  • 第一个函数不适用于 URL 中的破折号,例如此页面的 URL:stackoverflow.com/questions/1959062/…
  • @JonathanSampson 当我使用第二个函数时只有一个没有'http://'的域名,它会将当前域名附加到开头。例如:如果我输入 www.google.com,它会显示为 www.mydomain.com/www.google.com
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 我同意 WTF 声明和滞后,尽管我可能必须调整包含评论的 DB 列以包含更多字符以考虑 PHP 添加的字符
    【解决方案4】:

    我调整了 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
    

    希望对某人有所帮助。

    【讨论】:

    • 我一直在寻找适用于您示例中所有不同情况的答案。感谢您抽出宝贵时间与社区分享!干得好!
    • @user1846348 是正确的。它也不适用于 httpfun.com 之类的域
    • 这应该被修改,使(http)?(s)?(://)? 变成(https?://)?——我很确定这会解决前面提到的问题。 (仍然需要更新$1、$2等)
    • 这目前也捕获数字,例如 399.99
    【解决方案5】:

    改进 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.comwww.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 地址)

    【讨论】:

      【解决方案6】:

      在这里简单推荐一个有用的插件:External Linkshttps://wordpress.org/plugins/sem-external-links/

      【讨论】:

        【解决方案7】:

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

        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>', $text);
        
            //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+)\b/';
            $formatText = preg_replace($emailRegex, '<a href="mailto:$1" style="font-weight: normal;" target="_blank" title="$1">$1</a>', $formatText);
            $formatText = nl2br($formatText);
            return $formatText;
        }
        

        【讨论】:

          【解决方案8】:

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

          我还为文档添加了一些 cmets。

          /**
           * 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); 
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-03-10
            • 2020-01-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-07-12
            • 1970-01-01
            • 2018-06-15
            相关资源
            最近更新 更多