Comment remplacer des URL simples par des liens?

454

J'utilise la fonction ci-dessous pour faire correspondre les URL à l'intérieur d'un texte donné et les remplacer pour les liens HTML. L'expression régulière fonctionne très bien, mais actuellement je ne remplace que le premier match.

Comment puis-je remplacer toutes les URL? Je suppose que je devrais utiliser la commande exec , mais je n'ai pas vraiment compris comment le faire.

function replaceURLWithHTMLLinks(text) {
    var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/i;
    return text.replace(exp,"<a href='$1'>$1</a>"); 
}
Sergio del Amo
la source

Réponses:

351

Tout d'abord, rouler votre propre expression rationnelle pour analyser les URL est une idée terrible . Vous devez imaginer que c'est un problème suffisamment courant pour que quelqu'un ait écrit, débogué et testé une bibliothèque pour cela, selon les RFC . Les URI sont complexes - consultez le code pour l'analyse des URL dans Node.js et la page Wikipedia sur les schémas d'URI .

Il y a une tonne de cas extrêmes lorsqu'il s'agit d'analyser des URL: noms de domaine internationaux , TLD réels ( .museum) vs inexistants ( .etc), ponctuation étrange, y compris les parenthèses , ponctuation à la fin de l'URL, noms d'hôte IPV6, etc.

J'ai regardé une tonne de bibliothèques , et il y en a quelques-unes qui valent la peine d'être utilisées malgré certains inconvénients:

Bibliothèques que j'ai rapidement disqualifiées pour cette tâche:

Si vous insistez sur une expression régulière, la plus complète est l' URL regexp du composant , bien qu'elle détecte faussement certains TLD à deux lettres inexistants en la regardant.

Dan Dascalescu
la source
3
C'est dommage que ce URL regexp from Componentne soit pas commenté, une explication de ce qu'il fait serait utile. Autolinker.jsest très bien commenté et a des tests. La urlize.jsbibliothèque liée à dans la réponse de Vebjorn Ljosa semble également fonctionnelle et bien entretenue, même si elle n'a pas de tests.
Sam Hasler
1
Regex101.com "explique" automatiquement l'expression rationnelle, mais bonne chance avec ça :) J'ai aussi rapidement trouvé un cas d'échec avec un TLD invalide (même lien).
Dan Dascalescu
1
@SamHasler: Autolinker doit s'améliorer dans le domaine des TLD et IDN. Ajout de quelques tests .
Dan Dascalescu
2
Curieux que personne n'ait mentionné les efforts de John Gruber pour maintenir un modèle d'expression régulière d'URL . Ce n'est pas la seule / idéale solution au problème, mais en tout cas mérite d'être étudiée, si vous lancez votre propre solution. Je voulais juste ajouter cela comme référence.
oelna
2
@DanDascalescu Jetez un œil à ce markdown-it.github.io/linkify-it . Cette bibliothèque se concentre exactement sur une tâche: détecter les modèles de liens dans le texte. Mais j'espère que ça le fait bien. Par exemple, il prend en charge correctement unicode, y compris les caractères astraux. Et il prend en charge les TLD internationaux.
Vitaly
285

Remplacement des URL par des liens (réponse au problème général)

L'expression régulière dans la question manque beaucoup de cas marginaux. Lors de la détection d'URL, il est toujours préférable d'utiliser une bibliothèque spécialisée qui gère les noms de domaine internationaux, les nouveaux TLD comme .museum, les parenthèses et autres signes de ponctuation à l'intérieur et à la fin de l'URL, et de nombreux autres cas marginaux. Voir le billet de blog de Jeff Atwood The Problem With URLs pour une explication de certains des autres problèmes.

Le meilleur résumé des bibliothèques de correspondance d'URL se trouve dans la réponse de Dan Dascalescu+100
(en février 2014)


"Faire en sorte qu'une expression régulière remplace plus d'une correspondance" (réponse au problème spécifique)

Ajoutez un "g" à la fin de l'expression régulière pour activer la correspondance globale:

/ig;

Mais cela ne résout que le problème de la question où l'expression régulière ne remplaçait que la première correspondance. N'utilisez pas ce code.

Sam Hasler
la source
150

J'ai apporté quelques petites modifications au code de Travis (juste pour éviter toute redéclaration inutile - mais cela fonctionne très bien pour mes besoins, donc beau travail!):

function linkify(inputText) {
    var replacedText, replacePattern1, replacePattern2, replacePattern3;

    //URLs starting with http://, https://, or ftp://
    replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
    replacedText = inputText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>');

    //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
    replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
    replacedText = replacedText.replace(replacePattern2, '$1<a href="http://$2" target="_blank">$2</a>');

    //Change email addresses to mailto:: links.
    replacePattern3 = /(([a-zA-Z0-9\-\_\.])+@[a-zA-Z\_]+?(\.[a-zA-Z]{2,6})+)/gim;
    replacedText = replacedText.replace(replacePattern3, '<a href="mailto:$1">$1</a>');

    return replacedText;
}
cloud8421
la source
1
comment modifier ce code pour ne pas nuire aux objets intégrés et aux iframes .. (objets intégrés et iframes youtube)
Pradyut Bhattacharya
5
Il y a un bogue dans le code qui correspond aux adresses e-mail ici. [a-zA-Z]{2,6}devrait lire quelque chose dans le sens de (?:[a-zA-Z]{2,6})+afin de faire correspondre les noms de domaine plus complexes, par exemple [email protected].
Roshambo
1
J'ai rencontré quelques problèmes; tout d'abord, http: // ou http: // www (sans espace www, même SO analyse ce problème apparemment) créera un lien. Et des liens avec http: // www. domaine. com (sans espaces) créera un lien vide, puis un avec une balise de fermeture d'ancre attachée dans le champ href.
Alfred
1
Qu'en est-il des URL sans http://ou www? Cela fonctionnera-t-il pour ce type d'URL?
Nathan
2
J'ai essayé de modifier le message d'origine pour résoudre le problème de mailto, mais je dois ajouter au moins 6 caractères pour effectuer une modification. Mais si vous changez cette ligne: replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;cela replacePattern3 = /(\w+@[a-zA-Z_]+?(\.[a-zA-Z]{2,6})+)/gim;corrige le problème mailto :)
yourdeveloperfriend
70

A fait quelques optimisations au Linkify()code de Travis ci-dessus. J'ai également corrigé un bug où les adresses e-mail avec des formats de type de sous-domaine ne correspondaient pas (par exemple [email protected]).

De plus, j'ai changé l'implémentation pour prototyper la Stringclasse afin que les éléments puissent être mis en correspondance comme suit:

var text = '[email protected]';
text.linkify();

'http://stackoverflow.com/'.linkify();

Quoi qu'il en soit, voici le script:

if(!String.linkify) {
    String.prototype.linkify = function() {

        // http://, https://, ftp://
        var urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;

        // www. sans http:// or https://
        var pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim;

        // Email addresses
        var emailAddressPattern = /[\w.]+@[a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim;

        return this
            .replace(urlPattern, '<a href="$&">$&</a>')
            .replace(pseudoUrlPattern, '$1<a href="http://$2">$2</a>')
            .replace(emailAddressPattern, '<a href="mailto:$&">$&</a>');
    };
}
Roshambo
la source
Le meilleur à mon avis, car les fonctions du prototype rendent les choses tellement plus propres :)
MRVDOG
il semble que cela ne fonctionne pas avec ces adresses e-mail: [email protected] [email protected] etc.
Marco Gagliardi
@MarcoGagliardi Bonne prise. Fixé.
Roshambo
1
Cela ne fonctionne pas pour la chaîne "git clone [email protected]/ooo/bbb-cc-dd.git ". Il a cassé la chaîne en morceaux et créé plusieurs ancres comme celle-ci "git clone <a href="https://<a href="mailto:[email protected]"> [email protected] </a> / ooo / bbb-cc-dd.git "> https: // <a href="mailto:[email protected]"> [email protected] </a> /ooo/bbb-cc-dd.git </a> "
Jebin
1
Cela ne fonctionne pas avec les +noms d'utilisateur de messagerie, tels que [email protected]. Je l'ai corrigé avec le modèle d'e-mail /[\w.+]+@[a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim(notez le +dans les premières parenthèses), mais je ne sais pas si cela casse autre chose.
dchacke
24

Merci, ceci était vraiment utile. Je voulais également quelque chose qui lierait des choses qui ressemblaient à une URL - comme exigence de base, il lierait quelque chose comme www.yahoo.com, même si le préfixe de protocole http: // n'était pas présent. Donc, fondamentalement, si "www". est présent, il le liera et supposera qu'il s'agit de http: //. Je voulais aussi que les e-mails deviennent des liens mailto :. EXEMPLE: www.yahoo.com serait converti en www.yahoo.com

Voici le code avec lequel je me suis retrouvé (combinaison de code de cette page et d'autres choses que j'ai trouvées en ligne et d'autres choses que j'ai faites moi-même):

function Linkify(inputText) {
    //URLs starting with http://, https://, or ftp://
    var replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
    var replacedText = inputText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>');

    //URLs starting with www. (without // before it, or it'd re-link the ones done above)
    var replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
    var replacedText = replacedText.replace(replacePattern2, '$1<a href="http://$2" target="_blank">$2</a>');

    //Change email addresses to mailto:: links
    var replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;
    var replacedText = replacedText.replace(replacePattern3, '<a href="mailto:$1">$1</a>');

    return replacedText
}

Dans le 2e remplacement, la partie (^ | [^ /]) ne remplace www.wwhat.com que si elle n'est pas déjà préfixée par // - pour éviter la double liaison si une URL était déjà liée lors du premier remplacement. En outre, il est possible que www.wwhat.com soit au début de la chaîne, qui est la première condition "ou" dans cette partie de l'expression régulière.

Cela pourrait être intégré en tant que plugin jQuery comme Jesse P illustré ci-dessus - mais je voulais spécifiquement une fonction régulière qui n'agissait pas sur un élément DOM existant, parce que je prends le texte que j'ai et l'ajoute ensuite au DOM, et Je veux que le texte soit "lié" avant de l'ajouter, je passe donc le texte par cette fonction. Fonctionne très bien.

Travis
la source
1
Il y a un problème avec le 2ème modèle, qui correspond à lui-même "www.domain.com". Le problème existe lorsque l'URL contient une sorte de référent, comme: & location = http% 3A% 2F% 2Fwww.amazon.com% 2FNeil-Young% 2Fe% 2FB000APYJWA% 3Fqid% 3D1280679945% 26sr% 3D8-2-ent & tag = tra0c7 -20 & linkCode = ur2 & camp = 1789 & creative = 9325 - auquel cas le lien est à nouveau automatiquement lié. Une solution rapide consiste à ajouter le caractère "f" après la liste négative qui contient "/". Donc, l'expression est: replacePattern2 = /(^|[^\/f[)(www\.[\S E5E+(\b|$))
gim
Le code ci-dessus échouera à de nombreux tests pour les cas marginaux. Lors de la détection d'URL, il est préférable de s'appuyer sur une bibliothèque spécialisée. Voici pourquoi .
Dan Dascalescu
2
Je viens de l'exécuter sur une chaîne où certains des liens Web ont déjà des liens href. Dans ce cas, il échoue à gâcher les liens de travail existants.
AdamJones
17

L'identification des URL est délicate car elles sont souvent entourées de signes de ponctuation et parce que les utilisateurs n'utilisent souvent pas la forme complète de l'URL. De nombreuses fonctions JavaScript existent pour remplacer les URL par des hyperliens, mais je n'ai pas pu en trouver une qui fonctionne ainsi que le urlizefiltre dans le framework Web basé sur Python Django. J'ai donc porté la urlizefonction de Django en JavaScript:

https://github.com/ljosa/urlize.js

Un exemple:

urlize('Go to SO (stackoverflow.com) and ask. <grin>', 
       {nofollow: true, autoescape: true})
=> "Go to SO (<a href="http://stackoverflow.com" rel="nofollow">stackoverflow.com</a>) and ask. &lt;grin&gt;"

Le deuxième argument, s'il est vrai, provoque rel="nofollow"l'insertion. Le troisième argument, s'il est vrai, échappe aux caractères qui ont une signification particulière en HTML. Voir le fichier README .

Vebjorn Ljosa
la source
Fonctionne également avec une source html comme: www.web.com <a href =
"https: // github. Com">
@Paulius: si vous définissez l'option django_compatiblesur false, il gérera un peu mieux ce cas d'utilisation.
Vebjorn Ljosa
Django urlizene prend pas correctement en charge les TLD (du moins pas le port JS sur GitHub). Une bibliothèque qui gère correctement les TLD est JavaScript Linkify de Ben Alman .
Dan Dascalescu
Prise en charge de la détection d'URL avec des domaines de niveau supérieur supplémentaires même lorsque l'URL ne commence pas par «http» ou «www» a été ajoutée.
Vebjorn Ljosa
10

J'ai apporté une modification à Roshambo String.linkify () à l'adresse emailAddressPattern pour reconnaître les adresses aaa.bbb. @ Ccc.ddd

if(!String.linkify) {
    String.prototype.linkify = function() {

        // http://, https://, ftp://
        var urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;

        // www. sans http:// or https://
        var pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim;

        // Email addresses *** here I've changed the expression ***
        var emailAddressPattern = /(([a-zA-Z0-9_\-\.]+)@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6}))+/gim;

        return this
            .replace(urlPattern, '<a target="_blank" href="$&">$&</a>')
            .replace(pseudoUrlPattern, '$1<a target="_blank" href="http://$2">$2</a>')
            .replace(emailAddressPattern, '<a target="_blank" href="mailto:$1">$1</a>');
    };
}
Christian Koch
la source
Le code ci-dessus échouera à de nombreux tests pour les cas marginaux. Lors de la détection d'URL, il est préférable de s'appuyer sur une bibliothèque spécialisée. Voici pourquoi .
Dan Dascalescu
9

J'ai cherché sur google quelque chose de plus récent et j'ai rencontré celui-ci:

$('p').each(function(){
   $(this).html( $(this).html().replace(/((http|https|ftp):\/\/[\w?=&.\/-;#~%-]+(?![\w\s?&.\/;#~%"=-]*>))/g, '<a href="$1">$1</a> ') );
});

démo: http://jsfiddle.net/kachibito/hEgvc/1/

Fonctionne très bien pour les liens normaux.

dégénérer
la source
Qu'est-ce que les "liens normaux" ici? Regardez la fourchette de votre démo ici: jsfiddle.net/hEgvc/27 Les gens couvriraient à découvert et feraient cela facilement. L'URI n'est pas chose facile selon la RFC3986 et si vous souhaitez couvrir uniquement les "liens normaux", je suggère de suivre au moins cette expression régulière: ^ (([^: /? #] +):)? (// ([ ^ /? #] *))? ([^? #] *) (\? ([^ #] *))? (# (. *))?
Ivan
2
Je voulais dire n'importe quoi dans le format http://example.com/folder/folder/folder/ou https://example.org/blahetc. - juste votre format URL non fou typique qui correspondra à 95-99% des cas d'utilisation. J'utilise cela pour une zone administrative interne, donc je n'ai besoin de rien de fantaisiste pour attraper les cas de bord ou les liens de sécurité.
dégénéré
5

Cette solution fonctionne comme la plupart des autres et utilise en fait la même expression régulière que l'une d'entre elles, mais au lieu de renvoyer une chaîne HTML, cela retournera un fragment de document contenant l'élément A et tous les nœuds de texte applicables.

 function make_link(string) {
    var words = string.split(' '),
        ret = document.createDocumentFragment();
    for (var i = 0, l = words.length; i < l; i++) {
        if (words[i].match(/[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/gi)) {
            var elm = document.createElement('a');
            elm.href = words[i];
            elm.textContent = words[i];
            if (ret.childNodes.length > 0) {
                ret.lastChild.textContent += ' ';
            }
            ret.appendChild(elm);
        } else {
            if (ret.lastChild && ret.lastChild.nodeType === 3) {
                ret.lastChild.textContent += ' ' + words[i];
            } else {
                ret.appendChild(document.createTextNode(' ' + words[i]));
            }
        }
    }
    return ret;
}

Il y a quelques mises en garde, notamment avec les anciens supports IE et textContent.

voici une démo.

rlemon
la source
2
@DanDascalescu Au lieu de voter en aval, le lot peut fournir vos cas de bord.
rlemon
Est ce que j'ai besoin de? Jetez un œil à l' expression rationnelle des composants pour les URL . Mais si vous insistez, courez contre la suite de tests linkify de Ben Alman . J'ai commencé à contribuer à l'échec des tests, par exemple pour urlize , mais je me suis vite rendu compte que cela valait la peine de le faire uniquement pour de sérieux efforts de bibliothèque. Avec tout le respect que je vous dois, celle ci-dessus est une réponse StackOverflow, pas une bibliothèque open source essayant d'analyser correctement les URL.
Dan Dascalescu
2
il y a donc des cas marginaux. magnifique. ces réponses peuvent encore être utiles à d'autres et le fait de les voter en bloc semble être exagéré. Les autres réponses que vous avez commenté et apparemment downvoted do contenir des informations utiles (ainsi que votre réponse). tout le monde ne se prononcera pas contre ces cas, et tout le monde ne voudra pas utiliser une bibliothèque.
rlemon
Exactement. Ceux qui ne comprennent pas les limites des regexps sont ceux qui seront ravis de parcourir la première expression rationnelle de la réponse la plus votée et de l'exécuter. Ce sont ces personnes qui devraient utiliser le plus les bibliothèques.
Dan Dascalescu
1
Mais comment est cette justification pour voter contre chaque réponse avec une expression rationnelle qui n'est pas celle que vous préférez?
rlemon
4

Si vous devez afficher un lien plus court (uniquement le domaine), mais avec la même URL longue, vous pouvez essayer ma modification de la version de code de Sam Hasler publiée ci-dessus

function replaceURLWithHTMLLinks(text) {
    var exp = /(\b(https?|ftp|file):\/\/([-A-Z0-9+&@#%?=~_|!:,.;]*)([-A-Z0-9+&@#%?\/=~_|!:,.;]*)[-A-Z0-9+&@#\/%=~_|])/ig;
    return text.replace(exp, "<a href='$1' target='_blank'>$3</a>");
}
Artjom Kurapov
la source
3

Reg Ex: /(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]*)/ig

function UriphiMe(text) {
      var exp = /(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]*)/ig; 
      return text.replace(exp,"<a href='$1'>$1</a>");
}

Voici quelques chaînes testées:

  1. Retrouvez-moi sur www.google.com
  2. www
  3. Retrouvez-moi sur www. http://www.com
  4. Suivez-moi sur: http://www.nishantwork.wordpress.com
  5. http://www.nishantwork.wordpress.com
  6. Suivez-moi sur: http://www.nishantwork.wordpress.com
  7. https://stackoverflow.com/users/430803/nishant

Remarque: Si vous ne voulez pas passer wwwcomme valide, utilisez simplement ci-dessous reg ex: /(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig

Nishant Kumar
la source
Le code ci-dessus échouera à de nombreux tests pour les cas marginaux. Lors de la détection d'URL, il est TOUJOURS préférable de s'appuyer sur une bibliothèque spécialisée. Voici pourquoi .
Dan Dascalescu
3

Les avertissements concernant la complexité de l'URI doivent être notés, mais la réponse simple à votre question est:
pour remplacer chaque correspondance, vous devez ajouter l' /gindicateur à la fin du RegEx:
/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi

Moritz
la source
3
/**
 * Convert URLs in a string to anchor buttons
 * @param {!string} string
 * @returns {!string}
 */

function URLify(string){
  var urls = string.match(/(((ftp|https?):\/\/)[\-\w@:%_\+.~#?,&\/\/=]+)/g);
  if (urls) {
    urls.forEach(function (url) {
      string = string.replace(url, '<a target="_blank" href="' + url + '">' + url + "</a>");
    });
  }
  return string.replace("(", "<br/>(");
}

exemple simple

Zuhair Taha
la source
2

Rester simple! Dites ce que vous ne pouvez pas avoir plutôt que ce que vous pouvez avoir :)

Comme mentionné ci-dessus, les URL peuvent être assez complexes, surtout après le «?», Et toutes ne commencent pas par un «www». par exemplemaps.bing.com/something?key=!"£$%^*()&lat=65&lon&lon=20

Donc, plutôt que d'avoir une expression rationnelle complexe qui ne répondra pas à tous les cas extrêmes, et sera difficile à maintenir, que diriez-vous de celle beaucoup plus simple, qui fonctionne bien pour moi dans la pratique.

Rencontre

http(s):// (anything but a space)+

www. (anything but a space)+

Où `` n'importe quoi '' est [^'"<>\s] ... fondamentalement une allumette gourmande, vous amenant à rencontrer un espace, un devis, un support d'angle ou une fin de ligne

Aussi:

N'oubliez pas de vérifier qu'il n'est pas déjà au format URL, par exemple le texte contient href="..."ousrc="..."

Ajouter ref = nofollow (si approprié)

Cette solution n'est pas aussi "bonne" que les bibliothèques mentionnées ci-dessus, mais elle est beaucoup plus simple et fonctionne bien dans la pratique.

if html.match( /(href)|(src)/i )) {
    return html; // text already has a hyper link in it
    }

html = html.replace( 
            /\b(https?:\/\/[^\s\(\)\'\"\<\>]+)/ig, 
            "<a ref='nofollow' href='$1'>$1</a>" 
            );

html = html.replace( 
            /\s(www\.[^\s\(\)\'\"\<\>]+)/ig, 
            "<a ref='nofollow' href='http://$1'>$1</a>" 
            );

html = html.replace( 
             /^(www\.[^\s\(\)\'\"\<\>]+)/ig, 
            "<a ref='nofollow' href='http://$1'>$1</a>" 
            );

return html;
Andrew Murphy
la source
2

La détection correcte des URL avec la prise en charge des domaines internationaux et des caractères astraux n'est pas une chose triviale. linkify-itla bibliothèque construit des expressions rationnelles à partir de nombreuses conditions , et la taille finale est d'environ 6 kilo-octets :). Il est plus précis que toutes les bibliothèques, actuellement référencées dans la réponse acceptée.

Voir la démo de Linkify-it pour vérifier en direct tous les cas de bord et tester les vôtres.

Si vous devez lier la source HTML, vous devez d'abord l'analyser et répéter chaque jeton de texte séparément.

Vitaly
la source
1

J'ai écrit une autre bibliothèque JavaScript, cela pourrait être mieux pour vous car elle est très sensible avec le moins de faux positifs possibles, rapide et de petite taille. Je suis actuellement en train de le maintenir activement, alors testez-le dans la page de démonstration et voyez comment cela fonctionnerait pour vous.

lien: https://github.com/alexcorvi/anchorme.js

Alex C.
la source
Bibliothèque impressionnante. Merci beaucoup!
Serdar Değirmenci
0

J'ai dû faire le contraire, et faire des liens html juste dans l'URL, mais j'ai modifié votre regex et cela fonctionne comme un charme, merci :)

var exp = /<a\s.*href=='"{(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_ |!:,.;] * [- A-Z0-9 + & @ # \ /% = ~ _ |]) ['"]. *>. * <\ / A> / ig;

source = source.replace (exp, "$ 1");

la source
Je ne vois pas l'intérêt de votre regex. Il correspond à tout en remplaçant tout par tout. En effet, votre code ne fait rien.
Chad Grant
8
Je suppose que je devrais attendre de commenter pour permettre aux gens de terminer l'édition. Désolé.
Chad Grant
0

La détection des e-mails dans la réponse de Travitron ci-dessus ne fonctionnait pas pour moi, donc je l'ai étendue / remplacée par ce qui suit (code C #).

// Change e-mail addresses to mailto: links.
const RegexOptions o = RegexOptions.Multiline | RegexOptions.IgnoreCase;
const string pat3 = @"([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,6})";
const string rep3 = @"<a href=""mailto:$1@$2.$3"">$1@$2.$3</a>";
text = Regex.Replace(text, pat3, rep3, o);

Cela permet des adresses e-mail telles que " pré[email protected] ".

Uwe Keim
la source
Le code ci-dessus échouera à de nombreux tests pour les cas marginaux. Lors de la détection d'URL, il est TOUJOURS préférable de s'appuyer sur une bibliothèque spécialisée. Voici pourquoi .
Dan Dascalescu
Merci, @DanDascalescu Habituellement, il est toujours préférable de trop généraliser.
Uwe Keim
0

Après l'entrée de plusieurs sources, j'ai maintenant une solution qui fonctionne bien. Cela avait à voir avec l'écriture de votre propre code de remplacement.

Réponds .

Violon .

function replaceURLWithHTMLLinks(text) {
    var re = /(\(.*?)?\b((?:https?|ftp|file):\/\/[-a-z0-9+&@#\/%?=~_()|!:,.;]*[-a-z0-9+&@#\/%=~_()|])/ig;
    return text.replace(re, function(match, lParens, url) {
        var rParens = '';
        lParens = lParens || '';

        // Try to strip the same number of right parens from url
        // as there are left parens.  Here, lParenCounter must be
        // a RegExp object.  You cannot use a literal
        //     while (/\(/g.exec(lParens)) { ... }
        // because an object is needed to store the lastIndex state.
        var lParenCounter = /\(/g;
        while (lParenCounter.exec(lParens)) {
            var m;
            // We want m[1] to be greedy, unless a period precedes the
            // right parenthesis.  These tests cannot be simplified as
            //     /(.*)(\.?\).*)/.exec(url)
            // because if (.*) is greedy then \.? never gets a chance.
            if (m = /(.*)(\.\).*)/.exec(url) ||
                    /(.*)(\).*)/.exec(url)) {
                url = m[1];
                rParens = m[2] + rParens;
            }
        }
        return lParens + "<a href='" + url + "'>" + url + "</a>" + rParens;
    });
}
Mike Mestnik
la source
2
Le code ci-dessus (et la plupart des expressions régulières en général) échouera à de nombreux tests pour les cas limites. Lors de la détection d'URL, il est préférable de s'appuyer sur une bibliothèque spécialisée. Voici pourquoi .
Dan Dascalescu
Dan, existe-t-il une telle bibliothèque? Bien que dans ce cas, nous correspondions toujours à l'expression rationnelle ci-dessus afin que le code ne puisse jamais générer de déchets lorsque quelque chose comme des déchets (même si une autre bibliothèque certifie les déchets comme une URL / URI valide) est utilisé en entrée.
Mike Mestnik
0

Voici ma solution:

var content = "Visit https://wwww.google.com or watch this video: https://www.youtube.com/watch?v=0T4DQYgsazo and news at http://www.bbc.com";
content = replaceUrlsWithLinks(content, "http://");
content = replaceUrlsWithLinks(content, "https://");

function replaceUrlsWithLinks(content, protocol) {
    var startPos = 0;
    var s = 0;

    while (s < content.length) {
        startPos = content.indexOf(protocol, s);

        if (startPos < 0)
            return content;

        let endPos = content.indexOf(" ", startPos + 1);

        if (endPos < 0)
            endPos = content.length;

        let url = content.substr(startPos, endPos - startPos);

        if (url.endsWith(".") || url.endsWith("?") || url.endsWith(",")) {
            url = url.substr(0, url.length - 1);
            endPos--;
        }

        if (ROOTNS.utils.stringsHelper.validUrl(url)) {
            let link = "<a href='" + url + "'>" + url + "</a>";
            content = content.substr(0, startPos) + link + content.substr(endPos);
            s = startPos + link.length;
        } else {
            s = endPos + 1;
        }
    }

    return content;
}

function validUrl(url) {
    try {
        new URL(url);
        return true;
    } catch (e) {
        return false;
    }
}
AndroidDev
la source
0

Essayez la fonction ci-dessous:

function anchorify(text){
  var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
  var text1=text.replace(exp, "<a href='$1'>$1</a>");
  var exp2 =/(^|[^\/])(www\.[\S]+(\b|$))/gim;
  return text1.replace(exp2, '$1<a target="_blank" href="http://$2">$2</a>');
}

alert(anchorify("Hola amigo! https://www.sharda.ac.in/academics/"));

Moonis Abidi
la source
0

Essayez la solution ci-dessous

function replaceLinkClickableLink(url = '') {
let pattern = new RegExp('^(https?:\\/\\/)?'+
        '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|'+
        '((\\d{1,3}\\.){3}\\d{1,3}))'+
        '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+
        '(\\?[;&a-z\\d%_.~+=-]*)?'+
        '(\\#[-a-z\\d_]*)?$','i');

let isUrl = pattern.test(url);
if (isUrl) {
    return `<a href="${url}" target="_blank">${url}</a>`;
}
return url;
}
Rahul Hirve
la source