Как добавить тег привязки к URL из текстового ввода

Я хочу иметь возможность вводить введенный пользователем текст в поле комментария и проверять выражение типа 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="#" onclick="location.href='http://checkthis.us/'; return false;">http://checkthis.us/</a></div>

Ответ 1

Во-первых, запрос. Не делайте этого, прежде чем записывать данные в базу данных. Вместо этого сделайте это перед отображением данных конечному пользователю. Это сократит всю путаницу и даст вам больше гибкости в будущем.

Один пример найденный онлайн:

$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);
}

Ответ 2

Я адаптировал вариант регулярного выражения Джонатана Сампсона, чтобы он был более снисходительным к тому, что является доменом (не нужно, чтобы http (s) соответствовали критериям).

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

Работает для этих URL-адресов (и успешно не учитывает конечный период или запятую):

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

Надеюсь, что это поможет кому-то.

Ответ 3

Лично я хотел бы отметить его с JS прямо перед отображением, кажется более профессиональным и устойчивым, чем редактирование комментария пользователя.

Ответ 4

Уточнение ответа 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

Не работает для:
< br/" > 123.com/test (числовые домены без "www" )
Следите за популярным мнением........ сохраняйте средний (эллипсис)
Рост на 3,8% до 3,94 млн. С 3,79 млн. (в процентах и ​​десятичных знаках)
Отредактировано Andrew Brooke - 07.08.2013 19:57 (dd.mm.yyyy date)
10.1.1.1 (IP-адреса)

Ответ 5

Я бы предпочел сделать это на стороне сервера. Javascript имеет "задержку"; он запускается только тогда, когда все дерево HTML DOM было загружено и отображено в веб-браузере. Таким образом, он может занять (хотя и короткий), пока URL-адрес не распознается и не анализируется. Клиент может видеть, что ссылки моментально были заменены, пока он все еще сталкивается с контентом. Это может привести к "wtf?" опытом на стороне клиента. В наши дни это слишком быстро связано с рекламой/спамом/шпионским ПО. Вы должны избегать этого как можно больше. Не используйте JS для изменения загрузки контента, а делайте это только во время контролируемых пользователем событий (onclick, onchange, onfocus и т.д.). Используйте язык на стороне сервера для изменения содержимого до сохранения или отображения.

Итак, просто найдите PHP script, который анализирует текст (или использует регулярное выражение) для построения полноценных ссылок на основе URL в виде простого текста. Вы можете найти много здесь. Удачи.

Ответ 7

Вот мой код для форматирования всех ссылок внутри текста, включая электронные письма, URL-адреса с протоколом и без него.

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;
}