232 votes

Détecter les URL dans le texte avec JavaScript

Quelqu'un a-t-il des suggestions pour détecter les URL dans un ensemble de chaînes?

 arrayOfStrings.forEach(function(string){
  // detect URLs in strings and do something swell,
  // like creating elements with links.
});
 

Mise à jour: j'ai fini par utiliser cette expression rationnelle pour la détection de lien… Apparemment, plusieurs années plus tard.

 kLINK_DETECTION_REGEX = /(([a-z]+:\/\/)?(([a-z0-9\-]+\.)+([a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|local|internal))(:[0-9]{1,5})?(\/[a-z0-9_\-\.~]+)*(\/([a-z0-9_\-\.]*)(\?[a-z0-9+_\-\.%=&]*)?)?(#[a-zA-Z0-9!$&'()*+.=-_~:@/?]*)?)(\s+|$)/gi
 

L’assistant complet (avec le support facultatif du guidon) est à l’origine # 1654670 .

319voto

Crescent Fresh Points 54070

D'abord, vous avez besoin d'une bonne expression régulière qui correspond à l'url. C'est difficile à faire. Voir ici, ici et ici:

...presque tout est une URL valide. Il y quelques règles de ponctuation pour le fractionnement. En l'absence de toute la ponctuation, vous avez encore valide URL.

De vérifier la RFC attentivement et voir si vous peut construire un "invalid" de l'URL. L' les règles sont très flexibles.

Par exemple ::::: est une URL valide. Le chemin est - ":::::". Une jolie stupide nom de fichier, mais un nom de fichier valide.

Aussi, ///// est une URL valide. L' netloc ("hostname") "". Le chemin d'accès est - "///". Encore une fois, stupide. Aussi valides. Cette URL normalise à l' "///" qui est l'équivalent.

Quelque chose comme "bad://///worse/////" est parfaitement valide. Muet, mais valide.

De toute façon, cette réponse n'est pas conçue pour vous offrir le meilleur de la regex, mais plutôt une preuve de la façon de faire la chaîne d'emballage à l'intérieur du texte, avec le JavaScript.

OK, donc permet de l'utiliser: /(https?:\/\/[^\s]+)/g

Encore une fois, c'est un mauvais regex. Il aura beaucoup de faux positifs. Cependant, il est assez bon pour cet exemple.

function urlify(text) {
    var urlRegex = /(https?:\/\/[^\s]+)/g;
    return text.replace(urlRegex, function(url) {
        return '<a href="' + url + '">' + url + '</a>';
    })
    // or alternatively
    // return text.replace(urlRegex, '<a href="$1">$1</a>')
}

var text = "Find me at http://www.example.com and also at http://stackoverflow.com";
var html = urlify(text);

// html now looks like:
// "Find me at <a href="http://www.example.com">http://www.example.com</a> and also at <a href="http://stackoverflow.com">http://stackoverflow.com</a>"

Donc, en somme, essayez:

$$('#pad dl dd').each(function(element) {
    element.innerHTML = urlify(element.innerHTML);
});

206voto

Niaz Mohammed Points 318

Je sais que vous êtes probablement bien au-delà de la portée de cette question. Cependant, je suis sûr que, avec le temps, quelqu'un tombera sur la même question et devra probablement redescendre à plusieurs reprises vers Google pour trouver une solution concrète. Solution.

Voici ce que j'ai fini par utiliser comme regex:

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

La fonction de Cresent fonctionne comme un charme :), donc au total, c'est:

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

66voto

Adam Points 2611

J'ai googlé ce problème depuis un certain temps, puis il m'est apparu qu'il y est un Android méthode, android.texte.util.Linkify, qui utilise certaines assez robuste regexes pour accomplir cette tâche. Heureusement, Android est open source.

Ils utilisent un peu différents modèles pour la mise en correspondance des différents types d'url. Vous pouvez tous les trouver ici: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.0_r1/android/text/util/Regex.java#Regex.0WEB_URL_PATTERN

Si vous êtes préoccupé par les url qui correspondent à la WEB_URL_PATTERN, qui est, les url qui sont conformes à la RFC 1738 spec, vous pouvez utiliser ceci:

/((?:(http|https|Http|Https|rtsp|Rtsp):\/\/(?:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,64}(?:\:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,25})?\@)?)?((?:(?:[a-zA-Z0-9][a-zA-Z0-9\-]{0,64}\.)+(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnrwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eouw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw]))|(?:(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])))(?:\:\d{1,5})?)(\/(?:(?:[a-zA-Z0-9\;\/\?\:\@\&\=\#\~\-\.\+\!\*\'\(\)\,\_])|(?:\%[a-fA-F0-9]{2}))*)?(?:\b|$)/gi;

Voici le texte complet de la source:

"((?:(http|https|Http|Https|rtsp|Rtsp):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
+ "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
+ "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
+ "((?:(?:[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}\\.)+"   // named host
+ "(?:"   // plus top level domain
+ "(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
+ "|(?:biz|b[abdefghijmnorstvwyz])"
+ "|(?:cat|com|coop|c[acdfghiklmnoruvxyz])"
+ "|d[ejkmoz]"
+ "|(?:edu|e[cegrstu])"
+ "|f[ijkmor]"
+ "|(?:gov|g[abdefghilmnpqrstuwy])"
+ "|h[kmnrtu]"
+ "|(?:info|int|i[delmnoqrst])"
+ "|(?:jobs|j[emop])"
+ "|k[eghimnrwyz]"
+ "|l[abcikrstuvy]"
+ "|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])"
+ "|(?:name|net|n[acefgilopruz])"
+ "|(?:org|om)"
+ "|(?:pro|p[aefghklmnrstwy])"
+ "|qa"
+ "|r[eouw]"
+ "|s[abcdeghijklmnortuvyz]"
+ "|(?:tel|travel|t[cdfghjklmnoprtvwz])"
+ "|u[agkmsyz]"
+ "|v[aceginu]"
+ "|w[fs]"
+ "|y[etu]"
+ "|z[amw]))"
+ "|(?:(?:25[0-5]|2[0-4]" // or ip address
+ "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(?:25[0-5]|2[0-4][0-9]"
+ "|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1]"
+ "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
+ "|[1-9][0-9]|[0-9])))"
+ "(?:\\:\\d{1,5})?)" // plus option port number
+ "(\\/(?:(?:[a-zA-Z0-9\\;\\/\\?\\:\\@\\&\\=\\#\\~"  // plus option query params
+ "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
+ "(?:\\b|$)";

Si vous voulez être vraiment de fantaisie, vous pouvez tester les adresses e-mail ainsi. La regex pour des adresses email:

/[a-zA-Z0-9\\+\\.\\_\\%\\-]{1,256}\\@[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}(\\.[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25})+/gi

PS: Les domaines de haut niveau soutenus par-dessus les regex sont en cours à compter de juin 2007. Pour une liste à jour, vous aurez besoin de vérifier https://data.iana.org/TLD/tlds-alpha-by-domain.txt.

7voto

Gautam Sharma Points 93

La fonction peut être encore améliorée pour rendre des images aussi bien:

 function renderHTML(text) { 
    var rawText = strip(text)
    var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;   

    return rawText.replace(urlRegex, function(url) {   

    if ( ( url.indexOf(".jpg") > 0 ) || ( url.indexOf(".png") > 0 ) || ( url.indexOf(".gif") > 0 ) ) {
            return '<img src="' + url + '">' + '<br/>'
        } else {
            return '<a href="' + url + '">' + url + '</a>' + '<br/>'
        }
    }) 
} 
 

ou pour une image miniature liée à une image de taille complète:

 return '<a href="' + url + '"><img style="width: 100px; border: 0px; -moz-border-radius: 5px; border-radius: 5px;" src="' + url + '">' + '</a>' + '<br/>'
 

Et voici la fonction strip () qui prétraite l'uniformité de la chaîne de texte en supprimant tout code HTML existant.

 function strip(html) 
    {  
        var tmp = document.createElement("DIV"); 
        tmp.innerHTML = html; 
        var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;   
        return tmp.innerText.replace(urlRegex, function(url) {     
        return '\n' + url 
    })
} 
 

0voto

tmp.innerText n'est pas défini. Vous devriez utiliser tmp.innerHTML

 function strip(html) 
    {  
        var tmp = document.createElement("DIV"); 
        tmp.innerHTML = html; 
        var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;   
        return tmp.innerHTML .replace(urlRegex, function(url) {     
        return '\n' + url 
    })
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X