J'utilise une fonction linkify, qui détecte les modèles de type lien en utilisant regex et les remplace par des balises a pour révéler un lien cliquable.

La regex ressemble à ça :

    // http://, https://, ftp:// 
    var urlPattern = /\b(?![^<]*>|[^<>]*<\/)(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;
    /* Some explanations:
    (?!     # Negative lookahead start (will cause match to fail if contents match)
    [^<]*   # Any number of non-'<' characters
    >       # A > character
    |       # Or
    [^<>]*  # Any number of non-'<' and non-'>' characters
    </      # The characters < and /
     )      # End negative lookahead.
    */
    

Et remplace le lien comme ceci :

 return textInput.replace(urlPattern, '<a target="_blank" rel="noopener" href="$&">$&</a>')

L'expression régulière fonctionne parfaitement pour les liens dans le texte. Cependant, je l'utilise également dans le code HTML, tel que

<ul><li>Link: https://www.link.com</li></ul> //linkify not working
<ul><li>Link: https://www.link.com <br/></li></ul> //linkify working

Où seul le deuxième exemple fonctionne. Je ne sais pas pourquoi le comportement est différent et je serais très heureux d'avoir de l'aide de votre part. À quoi devrait ressembler mon regex, pour se lier sans rupture dans les éléments de la liste ?

0
Nixen85 19 oct. 2020 à 16:14

1 réponse

Meilleure réponse

Ciao,

Si j'ai bien compris votre problème, je pense que cette regex devrait être correcte pour détecter les liens dans les deux scénarios :

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

Essentiellement avec la première partie, nous segmentons de cette manière :

regex_segmentation

Ensuite, nous allons récupérer les différentes parties d'intérêt : la première partie est un groupe non capturant comme dans votre expression d'origine pour supprimer le protocole plus tard, si cela n'est vraiment pas nécessaire. La dernière partie prend la partie restante de l'URL

Pour la façon dont nous avons créé l'expression régulière, nous pouvons maintenant décider si nous prenons l'intégralité de l'URL ou uniquement la deuxième partie. Cela est évident en regardant en bas à droite de cette capture d'écran :

regex_processing

Maintenant, pour enregistrer les deux parties, nous pouvons prendre ce joli extrait :

const str = '<ul><li>Link: https://www.link.com</li></ul>';
var myRegexp = /\b(?![^<]*>)(?:https?|ftp):\/\/([a-z0-9-+&@#\/%?=~_|!:,.;]*)/gim;
var match = myRegexp.exec(str);
console.log(match[0]);
console.log(match[1]); 

Variantes possibles :

  • dans une situation comme celle présentée ci-dessus, vous pouvez simplifier davantage votre regex pour :

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

Obtenir le même résultat

  • si l'URL complète est suffisante, vous pouvez supprimer les parenthèses rondes du deuxième groupe

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

Passez une bonne journée,
Antonino

PS - Je suppose que vos exemples étaient censés être:

<ul><li>Link: https://www.link.com</li></ul>
<ul><li>Link: https://www.link.com <br/></li></ul>

C'est-à-dire avec https, http ou ftp, ce qui fait que le deuxième cas fonctionne avec votre regex d'origine

1
Antonino 20 oct. 2020 à 09:10