Как имитировать поведение автоматической пересылки стека
С PHP, как я могу имитировать поведение автоматической привязки Qaru (что BTW очень круто)?
Например, следующий URL:
http://www.stackoverflow.com/info/1925455/how-to-mimic-stackoverflow-auto-link-behavior
Преобразуется в это:
<a title="how to mimic stackoverflow auto link behavior" rel="nofollow" href="#" onclick="location.href='http://www.stackoverflow.com/info/1925455/how-to-mimic-stackoverflow-auto-link-behavior'; return false;">stackoverflow.com/info/1925455/…</a>
В этом случае мне не нужен атрибут title
.
И это:
http://pt.php.net/manual/en/function.base-convert.php#52450
Преобразуется в это:
<a rel="nofollow" href="#" onclick="location.href='http://pt.php.net/manual/en/function.base-convert.php#52450'; return false;">pt.php.net/manual/en/…</a>
Как я могу сделать аналогичную функцию в PHP?
PS: Посмотрите мои комментарии по этому вопросу для некоторых примеров и поведений.
Ответы
Ответ 1
Попробуйте это. URL-соответствие шаблона регулярных выражений от Daring Fireball.
/**
* Replace links in text with html links
*
* @param string $text
* @return string
*/
function auto_link_text($text)
{
// a more readably-formatted version of the pattern is on http://daringfireball.net/2010/07/improved_regex_for_matching_urls
$pattern = '(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\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) . "…";
}
return sprintf(\'<a rel="nofollow" href="%s">%s</a>\', $url, $text);
');
return preg_replace_callback($pattern, $callback, $text);
}
Текст ввода:
This is my text. I wonder if you know about asking questions on StackOverflow:
Check This out http://www.stackoverflow.com/questions/1925455/how-to-mimic-stackoverflow-auto-link-behavior
Also, base_convert php function?
http://pt.php.net/manual/en/function.base-convert.php#52450
http://pt.php.net/manual/en/function.base-convert.php?wtf=hehe#52450
Выходной текст:
This is my text. I wonder if you know about asking questions on StackOverflow:
Check This out <a rel="nofollow" href="http://www.stackoverflow.com/questions/1925455/how-to-mimic-stackoverflow-auto-link-behavior">stackoverflow.com/questions/1925455/…</a>
Also, base_convert php function?
<a rel="nofollow" href="http://pt.php.net/manual/en/function.base-convert.php#52450">pt.php.net/manual/en/…</a>
<a rel="nofollow" href="http://pt.php.net/manual/en/function.base-convert.php?wtf=hehe#52450">pt.php.net/manual/en/…</a>
Ответ 2
Это основано на том же регулярном выражении daringfireball.net, но добавляет немного больше логики, чем пример Эрика Коулмана, а также конфигурацию для максимальная глубина URL-адреса (SO, похоже, 50), максимальная глубина пути при усечении URL-адреса (SO, похоже, 2) и многоточия (…
).
Насколько я знаю, это реплицирует все функции SO-перезаписи SO, по крайней мере, до того, что было обсуждено до сих пор в комментариях и ответах здесь.
function auto_link_text($text) {
$pattern = '#\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))#';
return preg_replace_callback($pattern, 'auto_link_text_callback', $text);
}
function auto_link_text_callback($matches) {
$max_url_length = 50;
$max_depth_if_over_length = 2;
$ellipsis = '…';
$url_full = $matches[0];
$url_short = '';
if (strlen($url_full) > $max_url_length) {
$parts = parse_url($url_full);
$url_short = $parts['scheme'] . '://' . preg_replace('/^www\./', '', $parts['host']) . '/';
$path_components = explode('/', trim($parts['path'], '/'));
foreach ($path_components as $dir) {
$url_string_components[] = $dir . '/';
}
if (!empty($parts['query'])) {
$url_string_components[] = '?' . $parts['query'];
}
if (!empty($parts['fragment'])) {
$url_string_components[] = '#' . $parts['fragment'];
}
for ($k = 0; $k < count($url_string_components); $k++) {
$curr_component = $url_string_components[$k];
if ($k >= $max_depth_if_over_length || strlen($url_short) + strlen($curr_component) > $max_url_length) {
if ($k == 0 && strlen($url_short) < $max_url_length) {
// Always show a portion of first directory
$url_short .= substr($curr_component, 0, $max_url_length - strlen($url_short));
}
$url_short .= $ellipsis;
break;
}
$url_short .= $curr_component;
}
} else {
$url_short = $url_full;
}
return "<a rel=\"nofollow\" href=\"$url_full\">$url_short</a>";
}
Пример ввода:
This is my text. I wonder if you know about asking questions on StackOverflow:
Check This out http://www.stackoverflow.com/questions/1925455/how-to-mimic-stackoverflow-auto-link-behavior
Also, base_convert php function?
http://pt.php.net/manual/en/function.base-convert.php#52450
http://pt.php.net/manual/en/function.base-convert.php?wtf=hehe#52450
http://a.b/c/d/e/f/test
and http://a.b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/z/y/w/z/test
Пример вывода:
This is my text. I wonder if you know about asking questions on StackOverflow:
Check This out <a rel="nofollow" href="http://www.stackoverflow.com/questions/1925455/how-to-mimic-stackoverflow-auto-link-behavior">http://stackoverflow.com/questions/1925455/…</a>
Also, base_convert php function?
<a rel="nofollow" href="http://pt.php.net/manual/en/function.base-convert.php#52450">http://pt.php.net/manual/en/…</a>
<a rel="nofollow" href="http://pt.php.net/manual/en/function.base-convert.php?wtf=hehe#52450">http://pt.php.net/manual/en/…</a>
<a rel="nofollow" href="http://a.b/c/d/e/f/test">http://a.b/c/d/e/f/test</a>
and <a rel="nofollow" href="http://a.b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/z/y/w/z/test">http://a.b/c/d/…</a>
Ответ 3
Это преобразует образец строки в то, что вам нужно. Я оставил title
, поскольку он исходит из другого источника, а не только автономного URL-адреса, и вы сказали, что это не важно.
<?php
$urlInput="http://www.stackoverflow.com/questions/1925455/how-to-mimic-stackoverflow-auto-link-behavior";
preg_match('@http://(?:www\.)?(\S+/)\S*(?:\s|$)@i', $urlInput, $matches);
print('<a rel="nofollow" href="' . trim($matches[0]) . '">' . $matches[1] . '...</a>');
?>
Расширьте, если необходимо, для сканирования текста.
Если вы хотите сопоставить только определенное количество элементов пути URL, используйте это RE:
'@http://(?:www\.)?((?:\S+?/){1,3})\S*(?:\s|$)@i'
Это позволит извлечь до 3 элементов пути (хост и до двух каталогов). Вы можете изменить верхнюю границу в {1,3}
, чтобы определить максимальное количество элементов пути, которые вы хотите.
Изменено окончание \S
, чтобы разрешить нулевые совпадения.
Ответ 4
Если у вас есть предсказуемый URL-адрес, например SO, тогда вам должно быть легко схватить ссылки с регулярным выражением и отфильтровать те, которые соответствуют шаблону. Поэтому, если ваш URL http://example.com/stuff/1234
, то поиск http://example.com/stuff/1234/how-to-mimic
будет довольно тривиальным с регулярным выражением.
<?php
preg_match('/http:\/\/example.com\/(\w*)\/(\d)[\/*]/', $text, $matches);
if (is_array($matches))
{
foreach ($matches as $match)
{
// do something...
}
}
?>
Ответ 5
Основываясь на ответе Кевина Брока, но позволяет настраивать параметры (глубину и длину папки) и принимает URL-адреса без завершающих косых черт:
$url = 'http://www.stackoverflow.com/questions/1925455/how-to-mimic-stackoverflow-auto-link-behavior';
$output = '';
$params = array (
'length' => 10,
'depth' => 2,
);
preg_match ('@http://(?:www\.)?([^/?# ]+)(/\S+)?(?=\s|$)@i', $url, $matches);
if (isset ($matches[2]))
{
$parts = explode('/', substr($matches[2], 1));
if (count($parts) > $params['depth'] && strlen($matches[1].$matches[2]) > $params['length'])
$output = $matches[1].'/'.implode('/', array_slice($parts, 0, 2)).'/...';
else
$output = $matches[1].$matches[2];
}
else
$output = $matches[1];
echo '<a href="'.$matches[0].'">'.$output.'</a>';
Надеюсь, что это поможет
Ответ 6
См. Регулярное выражение (регулярное выражение) для соответствия URL:
https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?
PHP Пример: автоматическая ссылка URL внутри текста.
$text = preg_replace('@(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?)@', '<a href="$1">$1</a>', $text);