11
votes

Comment ajouter une balise d'ancrage à une URL à partir de la saisie de texte

Je veux pouvoir prendre le texte entré par l'utilisateur dans un champ de commentaire et vérifier l'expression de type URL, et s'il existe, ajoutez une balise d'ancrage (à URL) lorsque le commentaire est affiché.

J'utilise php Sur le côté serveur et JavaScript (avec jQuery) sur le client, je dois donc attendre de vérifier l'URL jusqu'à ce qu'il soit juste avant qu'il ne soit affiché? Ou ajoutez la balise d'ancrage avant d'insérer dans la base de données? P>

SO P>

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


3 commentaires

Je comprends ce que vous essayez d'atteindre, mais comme votre exemple est syntaxiquement invalide, je vous averti que: vous devez spécifier des URL externes avec un protocole (http: //), sinon Ils deviendront relatifs et indiquent votre propre domaine! Ainsi, http://blahblah.com et ainsi de suite.


Si vous faites ce type de manipulation avant d'insérer le commentaire dans la DB, vous aurez un problème si quelqu'un veut éditer son poste: il y aura du HTML au milieu de celui-ci ;; Donc, soit faire cette manipulation lorsque vous affichez ou stockez 2 versions du commentaire dans la DB (une "propre" et une "transformée / enrichie")


@Ballusc vous avez raison, je voulais changer cela dans l'affiché, mais j'ai eu une copie et une pâte heureux et oublié.


8 Réponses :


22
votes

Premier, une demande. Ne faites pas cela avant d'écrire les données à la base de données. Attendez-le plutôt avant d'afficher les données sur l'utilisateur final. Cela va réduire la confusion et vous permettra plus de flexibilité à l'avenir.

Un exemple trouvé en ligne suit: p> xxx pré>

et un beaucoup plus complet de DARINGFIREBALL.NET : P>

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


5 commentaires

Cela fonctionnerait, bien que j'ai bien peur du retard (il affichera beaucoup de commentaires à la fois)


Donner un coup de feu. Je doute que vous découvriez tout décalage notable.


c'est vraiment soigné (deuxième fonction)


La première fonction ne fonctionne pas avec des tirets dans les URL, comme dans l'URL de cette page: Stackoverflow.com/questions/1959062/... .


@JonathanSamPson Lorsque j'ai utilisé la deuxième fonction avec juste un nom de domaine sans 'http: //', il s'agit d'ajouter le nom de domaine actuel au début. ex: Si je tape sur www.google.com, il montre comme www.mydomain.com/www.google.com



2
votes

Personnellement, je le marquerais avec JS juste avant d'afficher, semble plus professionnel et durable que de modifier vous-même le commentaire de l'utilisateur.


0 commentaires

1
votes

Je préférerais faire cela sous le côté du serveur. Javascript a un "décalage"; Il ne fonctionne que lorsque l'ensemble de l'arborescence HTML DOM est chargé et affiché dans le WebBrowser. Ainsi, cela peut prendre un (bien que peu court), avant que l'URL soit reconnue et analysée. Le client peut voir que les liens ont été remplacés instantanément pendant qu'il est toujours confronté au contenu. Cela pourrait conduire à "WTF?" expériences du côté client. Ceci est aujourd'hui trop rapidement lié à la publicité / spam / spyware. Vous devriez éviter cela autant que possible. N'utilisez pas de JS pour modifier le contenu de la charge, le faire uniquement pendant les événements contrôlés par l'utilisateur (OnClick, Onchange, Onfocus, etc.). Utilisez le langage côté serveur pour modifier le contenu avant d'enregistrer ou d'afficher.

Donc, il suffit de rechercher un script PHP qui analyse le texte (ou utilise regex) pour construire des liens avec des liaisons complètes basés sur des URL en texte brut. Vous pouvez trouver un lot ici . Bonne chance.


1 commentaires

Je suis d'accord sur la déclaration WTF et le décalage, bien que je puisse avoir à ajuster la colonne de base de données contenant le commentaire pour conserver plus de caractères pour prendre en compte ceux qui sont ajoutés par le PHP.



13
votes

J'ai adapté l'option de regex de Jonathan Sampson de sorte qu'il soit plus clément sur ce qui est un domaine (pas besoin de HTTP (s) à qualifier).

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


4 commentaires

J'ai cherché une réponse partout qui fonctionne pour tous ces cas différents sont montrés dans votre exemple. Merci d'avoir pris le temps de partager cela avec la communauté! Bon travail!


@ user1846348 est correct. Il ne fonctionnera pas non plus pour un domaine comme httpfun.com


Cela devrait être adapté de sorte que (http)? (S)? (: //)? devient (https ?: //)? - Je suis sûr Cela résoudrait les problèmes mentionnés précédemment. (Il faut encore mettre à jour les 1 $, 2 $, etc.)


Cela capture également des chiffres, comme 399,99



2
votes

Raffinage de la réponse de Markd pour éviter les liens sur les décimales, les pourcentages, les dates numériques (10.3.2001), les adresses ellipsis et IP: xxx

fonctionne pour:

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-exemple.com
http: // ex-exemple.com
http: // ex-exemple.com/test-url_charars.php?param1=val1 .
http: // ex-exemple.com/test-url_chars?param1=value1¶m2=val+with%20Spaces

ne fonctionne pas pour:


123.com/test (domaines numériques sans 'www')
Continuez la presse de l'opinion populaire ........ Gardez la moyenne (ellipsis)
Hausse de 3,8% à 3,94 millions de 3,79 millions de dollars (pourcentages et décimales)
Édité par Andrew Brooke - 07.08.2013 19:57 (dates DD.MM.YYYY)

10.1.1.1 (adresses IP)


0 commentaires

0
votes

suggère simplement un plugin utile ici: liens externes https: / /wordpress.org/plugins/sem-external-links/


0 commentaires

3
votes

Voici mon code pour formater tous les liens à l'intérieur du texte, y compris les courriels, les URL avec et sans protocole.

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


0 commentaires

0
votes

J'ai une petite mise à jour de la réponse acceptée qui fonctionne également pour des liens sans protocole (liens sans http (s): //) - avant d'être liés mais comme des liens relatifs qui ne fonctionnaient pas.

J'ai également ajouté quelques commentaires pour la documentation. P>

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


0 commentaires