Précédent   Forum des professionnels en informatique > Webmasters - Développement Web > JavaScript
JavaScript Forum programmation JavaScript. Lire : Cours JavaScript, FAQ JavaScript, Toutes les FAQ JavaScript et Sources JavaScript
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 29/05/2011, 20h06   #1
Invité régulier
 
Inscription : avril 2009
Messages : 13
Détails du profil
Informations forums :
Inscription : avril 2009
Messages : 13
Points : 6
Points : 6
Par défaut Expression régulière pour les Urls

Bonjour,

Voilà j'aimerais (en JavaScript) remplacer toutes les urls par des liens <a href=...>...</a>

Donc j'ai une epxression régulière pour capter les liens :
Code :
1
2
var replacePattern1 = /(\b(https?):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
var replacedText = inputText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>');
Seulement le problème c'est que si une url est déjà dans un lien il la capte quand même.

Du coup j'aimerais changer l'expression régulière pour lui dire de ne pas traiter les liens s'il ya un '>' devant le http (donc quand l'url est déjà dans une balise <a href=...>...</a>).

J'ai essayé ceci :
Code :
1
2
var replacePattern1 = /^[^>](\b(https?):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
var replacedText = inputText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>');
Du coup il ne traite plus les url qui sont déjà dans un lien <a> mais par contre il ne traite plus non plus les url qui ne sont pas sous forme de lien <a> :'(

Avez-vous une idée de comment faire une expression régulière qui fasse ce que je souhaite?

Merci d'avance
scriptiz est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/05/2011, 22h22   #2
Rédacteur/Modérateur
 
Avatar de SpaceFrog
 
Homme
Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Analyste Programmeur
Inscription : mars 2002
Messages : 30 010
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Royaume-Uni

Informations professionnelles :
Activité : Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Analyste Programmeur
Secteur : Industrie

Informations forums :
Inscription : mars 2002
Messages : 30 010
Points : 45 094
Points : 45 094
Code :
var replacePattern1 = /^[^>]\s*((https?):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
__________________
Ma page Developpez
Président du CCMPTP (Comité Contre le Mot "Problème" dans les Titres de Posts)
Deux règles du succès: 1) Ne communiquez jamais à quelqu'un tout votre savoir...
Votre post est résolu ? Alors n'oubliez pas le Tag


réalisations :www.planet-languages.com|www.saftair.com| www.ouestisol.fr | www.sebemex.fr | www.extramiante.fr | www.sistac-alizay.fr | www.acoustishop.fr | www.litt.fr | www.ouestventil.fr
SpaceFrog est actuellement connecté   Envoyer un message privé Réponse avec citation 01
Vieux 29/05/2011, 22h48   #3
Invité régulier
 
Inscription : avril 2009
Messages : 13
Détails du profil
Informations forums :
Inscription : avril 2009
Messages : 13
Points : 6
Points : 6
Merci spacefrog, ça marche bien pour ne pas prendre les urls précédées de > comme :
>http://www.google.com


Par contre ça ne prend plus non plus les url qui ne sont pas précédées du > comme :
http://www.google.com

(même avec des espaces devant ou derrière).

Résultat des tests : http://awesomescreenshot.com/014dvli38

Donc retour à la case départ
scriptiz est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 08h35   #4
Rédacteur/Modérateur
 
Avatar de SpaceFrog
 
Homme
Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Analyste Programmeur
Inscription : mars 2002
Messages : 30 010
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Royaume-Uni

Informations professionnelles :
Activité : Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Analyste Programmeur
Secteur : Industrie

Informations forums :
Inscription : mars 2002
Messages : 30 010
Points : 45 094
Points : 45 094
arf ...évidemment,
et avec une assertion ?
Code :
var replacePattern1 = /^(?!=>)\s*((https?):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
__________________
Ma page Developpez
Président du CCMPTP (Comité Contre le Mot "Problème" dans les Titres de Posts)
Deux règles du succès: 1) Ne communiquez jamais à quelqu'un tout votre savoir...
Votre post est résolu ? Alors n'oubliez pas le Tag


réalisations :www.planet-languages.com|www.saftair.com| www.ouestisol.fr | www.sebemex.fr | www.extramiante.fr | www.sistac-alizay.fr | www.acoustishop.fr | www.litt.fr | www.ouestventil.fr
SpaceFrog est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 15h01   #5
Invité régulier
 
Inscription : avril 2009
Messages : 13
Détails du profil
Informations forums :
Inscription : avril 2009
Messages : 13
Points : 6
Points : 6
Toujours pas

Je teste avec ceci : http://www.regular-expressions.info/...ptexample.html

Et le met comme subject string celle ci :
_http://www.google.be/_

(les _ étant en fait des espaces).

Je commence à croire que c'est tout bonnement impossible... :s
scriptiz est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 16h34   #6
Membre Expert
 
Avatar de Watilin
 
Homme Matilin Torre
Étudiant
Inscription : juin 2010
Messages : 679
Détails du profil
Informations personnelles :
Nom : Homme Matilin Torre
Âge : 23
Localisation : France, Ille et Vilaine (Bretagne)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2010
Messages : 679
Points : 1 202
Points : 1 202
Je crois qu'il y a un problème de syntaxe avec ton assertion Spaffy. En plus, on peut pas regarder en arrière avec les assertions. Et pour ajouter au drame, on peut pas faire de référence arrière en JavaScript…

Moi je propose ça mais c'est pas parfait non plus : s'il y a une balise, même autre que <a>, autour du lien, il n'est pas traité…
Code :
1
2
var replacePattern1 = /([^<>"'\s]\s*)(\b(https?):\/\/[-\w+&@#\/%?=~|!:,.;]*[-\w+&@#\/%=~|])(\s*[^<>"'\s])/gi;
var replacedText = inputText.replace(replacePattern1, '$1<a href="$2" target="_blank">$2</a>$4');
Au fait j'ai viré l'option m : vu qu'on ne se sert pas des ancres ^ et $, elle est inutile. Et j'ai aussi remplacé tous les [A-Z0-9_] par des [\w].

Sinon je pense que pour cibler précisément le problème, une regex ne suffira pas. Il faut scripter un peu autour…
__________________
Disposition de clavier ergonomique française : Bépo
Watilin est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 17h58   #7
Futur Membre du Club
 
Inscription : mai 2011
Messages : 14
Détails du profil
Informations forums :
Inscription : mai 2011
Messages : 14
Points : 15
Points : 15
Par défaut Prendre le taureau par la queue

Citation:
Envoyé par Watilin Voir le message
En plus, on peut pas regarder en arrière avec les assertions. Et pour ajouter au drame, on peut pas faire de référence arrière en JavaScript…
Pourquoi dans ce cas ne pas plutôt exclure par la fin plutôt que par le début ? Ne pas autoriser "> après le href et </a> après le titre.
ohnomorejmmings est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 18h04   #8
Futur Membre du Club
 
Inscription : mai 2011
Messages : 14
Détails du profil
Informations forums :
Inscription : mai 2011
Messages : 14
Points : 15
Points : 15
Par défaut Exemple de code et méthode alternative

Citation:
Envoyé par scriptiz Voir le message
Voilà j'aimerais (en JavaScript) remplacer toutes les urls par des liens <a href=...>...</a>
C'est un problème assez commun il me semble. T'as regardé du côté de CodeS-SourceS & Cie ? Sinon un compromis c'est de faire un split au niveau des espaces du texte à traiter puis d'utiliser une expression régulière sur chaque chaîne et enfin d'assembler tout ce petit monde.
ohnomorejmmings est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 18h53   #9
Membre Expert
 
Avatar de Watilin
 
Homme Matilin Torre
Étudiant
Inscription : juin 2010
Messages : 679
Détails du profil
Informations personnelles :
Nom : Homme Matilin Torre
Âge : 23
Localisation : France, Ille et Vilaine (Bretagne)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2010
Messages : 679
Points : 1 202
Points : 1 202
Citation:
Envoyé par ohnomorejmmings Voir le message
Pourquoi dans ce cas ne pas plutôt exclure par la fin plutôt que par le début ? Ne pas autoriser "> après le href et </a> après le titre.
C'est pas si évident de détecter le ">, il peut y avoir d'autres attributs, comme par exemple target.

Moi je suis parti sur une autre idée : quand je tombe sur une url, que je détecte avec la regex, je rembobine jusqu'au dernier < avec lastIndexOf, et je détecte simplement si c'est une balise <a> ouvrante :
Dans ce cas je ne fais rien. Dans tous les autres cas, je transforme l'url en lien. Avec cette méthode je considère à la fois les balises autres que <a> et les liens qui concernent une autre url rencontrée plus tôt (car il y aurait une balise fermante).

Et voilà ce que ça donne :
Code JS :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var replacePattern1 = /\bhttps?:\/\/[-\w+&@#\/%?=~|!:,.;]*[-\w+&@#\/%=~|]/gi;
var previousIndex = 0;
var replacedText = '';
var matching;
 
while (matching = replacePattern1.exec(inputText)) {
 
	var url = matching[0];
 
	// j'ajoute le texte qui n'a pas besoin d'être traité
	var index = inputText.indexOf(url, previousIndex);
	replacedText += inputText.substring(previousIndex, index);
 
	// je rembobine jusqu'au dernier "<"
	var rewound = inputText.substring(inputText.lastIndexOf('<', index), replacePattern1.lastIndex);
 
	if (/<\s*a/i.test(rewound)) {
		// je ne fais rien
		replacedText += url;
	} else {
		// je transforme le lien
		replacedText += '<a href="' + url + '" target="_blank">' + url + '</a>';
	}
 
	previousIndex = replacePattern1.lastIndex;
}
replacedText += inputText.substr(previousIndex);
__________________
Disposition de clavier ergonomique française : Bépo
Watilin est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 19h01   #10
Invité régulier
 
Inscription : avril 2009
Messages : 13
Détails du profil
Informations forums :
Inscription : avril 2009
Messages : 13
Points : 6
Points : 6
Merci Watilin

Mais de nouveau je ne parviens pas à faire des match avec les urls valident sur le testeurs d'url que j'ai donné plus haut :s

Tu l'a testée sur des liens toi?
scriptiz est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 19h15   #11
Membre Expert
 
Avatar de Watilin
 
Homme Matilin Torre
Étudiant
Inscription : juin 2010
Messages : 679
Détails du profil
Informations personnelles :
Nom : Homme Matilin Torre
Âge : 23
Localisation : France, Ille et Vilaine (Bretagne)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2010
Messages : 679
Points : 1 202
Points : 1 202
Bien sûr, voilà mon jeu de tests :
Code JS :
1
2
3
4
var inputText = 'Test 1 : test de la regex, transformer : https://www.machin.org/le%20singe.ape?num=0,42#hash <br />\n\
Test 2 : href, ne pas transformer : <a href="http://chose.fr">chose</a><br />\n\
Test 3 : balise a, ne pas transformer : <a>http://www.truc.net</a><br />\n\
Test 4 : transformer après une <em>balise quelconque :</em> http://www.bidule.com';

Je pense qu'il faut retirer les / avec ton testeur.
__________________
Disposition de clavier ergonomique française : Bépo
Watilin est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 22h09   #12
Invité régulier
 
Inscription : avril 2009
Messages : 13
Détails du profil
Informations forums :
Inscription : avril 2009
Messages : 13
Points : 6
Points : 6
Ah bah en effet ce testeur n'est vraiment pas bon il déconne tout le temps, du coup je teste directement dans mon code maintenant

Mais bon je galère là, toujours des problèmes

Avec ton code avec le lastIndexOf ça me retire carrèment les messages sans liens Et ça retire aussi ce qui suit le dernier lien bien souvent ^^

Par contre pour ceci c'est pas mal bien qu'avec quelques bugs

Code :
1
2
var replacePattern1 = /([^<>"'\s]\s*)(\b(https?):\/\/[-\w+&@#\/%?=~|!:,.;]*[-\w+&@#\/%=~|])(\s*[^<>"'\s])/gi;
var replacedText = inputText.replace(replacePattern1, '$1<a href="$2" target="_blank">$2</a>$4');
Ca fonctionne presque bien hormis le fait qu'il ne me traite pas complètement certains liens, et que parfois il ne traite que le premier :s

Donc voici ma fonction linkify :
Code :
1
2
3
4
5
6
function linkify(inputText) {
	var replacePattern1 = /([^<>"'\s]\s*)(\b(https?):\/\/[-\w+&@#\/%?=~|!:,.;]*[-\w+&@#\/%=~|])(\s*[^<>"'\s])/gi;
	var replacedText = inputText.replace(replacePattern1, '$1<a href="$2" target="_blank">$2</a>$4');
 
	return replacedText;
}
Et voici quelques exemples de ce qu'elle reçoit (précédé par Before et de ce qu'elle renvoie (précédé par After) :

Exemple où seul le premier lien est transformé :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Before :
<br> <b>Attention, nous ne demanderons jamais votre mot de passe quoi qu'il arrive, si ce message vous le demande, veuillez ne pas y rèpondre et nous en faire part immèdiatement</b><br>  <br>  Bonjour Anael,
<br>
<br>Je me permet de faire un petit test : http://www.google.be    http://google.be 
<br>
<br>Héhé si ça fonctionne c'est cool : www.google.be www.gmail.com<br> 
                  <br>
 
 
After :
<br> <b>Attention, nous ne demanderons jamais votre mot de passe quoi qu'il arrive, si ce message vous le demande, veuillez ne pas y rèpondre et nous en faire part immèdiatement</b><br>  <br>  Bonjour Anael,
<br>
<br>Je me permet de faire un petit test : <a href="http://www.google.be" target="_blank">http://www.google.be</a>    http://google.be 
<br>
<br>Héhé si ça fonctionne c'est cool : www.google.be www.gmail.com<br> 
                  <br>
Exemple où un lien n'est pas transformé complètement (le e final n'est pas prit en compte :s
Code :
1
2
3
4
5
6
7
8
9
10
11
12
Before :
<br> <b>Attention, nous ne demanderons jamais votre mot de passe quoi qu'il arrive, si ce message vous le demande, veuillez ne pas y rèpondre et nous en faire part immèdiatement</b><br>  <br>  Bonjour http://google.be
<br>
<br>Yeah<br> 
                  <br>
 
 
After :
<br> <b>Attention, nous ne demanderons jamais votre mot de passe quoi qu'il arrive, si ce message vous le demande, veuillez ne pas y rèpondre et nous en faire part immèdiatement</b><br>  <br>  Bonjour <a href="http://google.b" target="_blank">http://google.b</a>e
<br>
<br>Yeah<br> 
                  <br>

Exemple où tous les liens sont prit en comptes, mais où les m du .com ne sont pas repris dans l'url :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Brefore :
<br> <b>Attention, nous ne demanderons jamais votre mot de passe quoi qu'il arrive, si ce message vous le demande, veuillez ne pas y rèpondre et nous en faire part immèdiatement</b><br>  <br>  Bonjour ceci est un http://www.test.net afin de vérifier si http://www.google.com
<br>
<br>Tout fonctionne-t-il bien? http://www.super.com
<br>
<br>Au revoir<br> 
                  <br>
 
 
After :
<br> <b>Attention, nous ne demanderons jamais votre mot de passe quoi qu'il arrive, si ce message vous le demande, veuillez ne pas y rèpondre et nous en faire part immèdiatement</b><br>  <br>  Bonjour ceci est un <a href="http://www.test.net" target="_blank">http://www.test.net</a> afin de vérifier si <a href="http://www.google.co" target="_blank">http://www.google.co</a>m
<br>
<br>Tout fonctionne-t-il bien? <a href="http://www.super.co" target="_blank">http://www.super.co</a>m
<br>
<br>Au revoir<br> 
                  <br>

Et un petit dernier qui n'est de nouveau pas complet au niveau du lien :
Code :
1
2
3
4
5
6
7
8
Brefore :
<br> <b>Attention, nous ne demanderons jamais votre mot de passe quoi qu'il arrive, si ce message vous le demande, veuillez ne pas y rèpondre et nous en faire part immèdiatement</b><br>  <br>  Test : http://www.supersite.net/dossier/fonctions.js<br> 
                  <br>
 
 
After :
<br> <b>Attention, nous ne demanderons jamais votre mot de passe quoi qu'il arrive, si ce message vous le demande, veuillez ne pas y rèpondre et nous en faire part immèdiatement</b><br>  <br>  Test : <a href="http://www.supersite.net/dossier/fonctions.j" target="_blank">http://www.supersite.net/dossier/fonctions.j</a>s<br> 
                  <br>

Sinon ce qui est génial c'est qu'il ne traite pas les liens déjà existant ça c'est vraiment parfait, mais ce qu'il faudrait c'est qu'il traite bien les url qu'il trouve :s Je suis vraiment hors jeu pour ce niveau de Regex ^^
scriptiz est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/05/2011, 00h44   #13
Membre Expert
 
Avatar de Watilin
 
Homme Matilin Torre
Étudiant
Inscription : juin 2010
Messages : 679
Détails du profil
Informations personnelles :
Nom : Homme Matilin Torre
Âge : 23
Localisation : France, Ille et Vilaine (Bretagne)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2010
Messages : 679
Points : 1 202
Points : 1 202
Oups. J'avais bêtement oublié de traiter la fin de la chaîne dans mon code. C'est corrigé !

Pour la version que tu as choisie, et les tests que tu as faits, je vois trois cas :
1– les liens se suivent. Les parties $1 et $4 de la regex se chevauchent d'un lien à l'autre, du coup le second passe à la trappe. On va s'en sortir avec la proposition de ohnomorejmmings : utiliser une assertion à la fin.

2– Pour les liens qui ne commence pas par http, c'est normal qu'ils ne soient pas transformés, c'était déjà le comportement de ta regex de départ.

3– le dernier caractère est oublié. Ça arrive aux fins de ligne : le moteur de regex doit trouver un caractère qui correspond à [^<>"'\s], or il n'y en plus dans la ligne, alors il en grignote un de l'url. Pour corriger ça il suffit de rajouter un point d'interrogation.

Ça plus d'autres problèmes, par exemple un texte qui commence par un lien, ça donne une regex comme ça :
Code regex :
/((?:^|[^<>"'])\s*)((https?):\/\/[-\w+&@#\/%?=~|!:,.;]*[-\w+&@#\/%=~|])(?=\s*[^<>"'\s]?)/gim
Comme l'assertion finale n'est pas capturante, on ne doit plus utiliser $4 :
Code JS :
return inputText.replace(replacePattern1, '$1<a href="$2" target="_blank">$2</a>');
N'hésite pas à faire d'autres tests… Comme tu l'as vu, j'oublie des cas
__________________
Disposition de clavier ergonomique française : Bépo
Watilin est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/05/2011, 07h48   #14
Invité régulier
 
Inscription : avril 2009
Messages : 13
Détails du profil
Informations forums :
Inscription : avril 2009
Messages : 13
Points : 6
Points : 6
Et bien sérieusement je ne pensais pas que c'était faisable je ne sais pas comment te remercier Watilin

J'ai testé tout mes cas et bien d'autres et n'ai rencontré aucun problème

Pour les liens qui commencent par www. j'avais oublié que c'était voulu, seuls ceux qui ont http seront transformés.

Donc voilà je pense que c'est désormais réglé, un tout tout grand merci à tout le monde pour votre aide elle fut vraiment précieuse!
scriptiz est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 17h08.


 
 
 
 
Partenaires

Hébergement Web