Come sostituire URL semplici con collegamenti?


454

Sto usando la funzione seguente per abbinare gli URL all'interno di un determinato testo e sostituirli con collegamenti HTML. L'espressione regolare funziona alla grande, ma attualmente sto solo sostituendo la prima partita.

Come posso sostituire tutto l'URL? Immagino che dovrei usare il comando exec , ma non ho davvero capito come farlo.

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

Risposte:


351

Prima di tutto, lanciare il tuo regexp per analizzare gli URL è un'idea terribile . Devi immaginare che questo sia un problema abbastanza comune che qualcuno ha scritto, eseguito il debug e testato una libreria per questo, secondo le RFC . Gli URI sono complessi : controlla il codice per l'analisi degli URL in Node.js e la pagina Wikipedia sugli schemi URI .

Ci sono un sacco di casi limite quando si tratta di analizzare gli URL: nomi di dominio internazionali , TLD effettivi ( .museum) vs. inesistenti ( .etc), punteggiatura strana tra parentesi , punteggiatura alla fine dell'URL, nomi host IPV6 ecc.

Ho esaminato un sacco di librerie e ce ne sono alcune che vale la pena usare nonostante alcuni aspetti negativi:

Librerie che ho squalificato rapidamente per questo compito:

Se insisti su un'espressione regolare, la più completa è l' URL regexp di Component , sebbene rileverà erroneamente alcuni TLD inesistenti di due lettere osservandolo.


3
È un peccato che URL regexp from Componentnon sia commentato, una spiegazione di ciò che sta facendo sarebbe utile. Autolinker.jsè commentato molto bene e ha dei test. Anche la urlize.jsbiblioteca collegata nella risposta di Vebjorn Ljosa sembra ricca di funzionalità e ben mantenuta, sebbene non abbia test.
Sam Hasler,

1
Regex101.com "spiega" automaticamente la regexp, ma buona fortuna con questo :) Ho anche trovato rapidamente un caso di errore con un TLD non valido (stesso collegamento).
Dan Dascalescu,

1
@SamHasler: Autolinker deve migliorare nell'area TLD e IDN. Aggiunti alcuni test .
Dan Dascalescu,

2
Curioso che nessuno abbia menzionato gli sforzi di John Gruber nel mantenere un pattern regex URL . Non è l'unica / soluzione ideale al problema, ma in ogni caso vale la pena indagare, se stai realizzando la tua soluzione. Volevo solo aggiungere questo come riferimento.
oelna,

2
@DanDascalescu Dai un'occhiata a questo markdown-it.github.io/linkify-it . Questa libreria si concentra esattamente su un compito: rilevare i modelli di collegamento nel testo. Ma spero, lo fa bene. Ad esempio, ha il supporto Unicode corretto, inclusi i caratteri astrali. E supporta i TLD internazionali.
Vitaly,

285

Sostituzione di URL con collegamenti (risposta al problema generale)

L'espressione regolare nella domanda manca di molti casi limite. Quando si rilevano gli URL, è sempre meglio utilizzare una libreria specializzata che gestisca nomi di dominio internazionali, nuovi TLD come .museum, parentesi e altri segni di punteggiatura all'interno e alla fine dell'URL e molti altri casi limite. Vedi il post sul blog di Jeff Atwood The Problem With URLs per una spiegazione di alcuni degli altri problemi.

Il miglior riepilogo delle librerie di corrispondenza URL è nella risposta di Dan Dascalescu+100
(a febbraio 2014)


"Crea un'espressione regolare sostituisci più di una corrispondenza" (Risposta al problema specifico)

Aggiungi una "g" alla fine dell'espressione regolare per abilitare la corrispondenza globale:

/ig;

Ma questo risolve solo il problema nella domanda in cui l'espressione regolare stava sostituendo solo la prima corrispondenza. Non usare quel codice.


150

Ho apportato alcune piccole modifiche al codice di Travis (solo per evitare inutili dichiarazioni ridotte - ma funziona benissimo per le mie esigenze, quindi un bel lavoro!):

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

1
come modificare questo codice per non danneggiare oggetti incorporati e iframe ... (oggetti incorporati e iframe di YouTube)
Pradyut Bhattacharya,

5
C'è un bug nel codice che corrisponde agli indirizzi email qui. [a-zA-Z]{2,6}dovrebbe leggere qualcosa sulla (?:[a-zA-Z]{2,6})+falsariga di per abbinare nomi di dominio più complicati, ad esempio email@example.co.uk.
Roshambo,

1
Ho riscontrato alcuni problemi; prima solo http: // o http: // www (senza spazio www, anche se SO analizza questo errore apparentemente) creerà un collegamento. E collegamenti con http: // www. dominio. com (senza spazi) creerà un collegamento vuoto e poi uno con un tag di chiusura dell'ancora allegato nel campo href.
Alfred,

1
Che dire degli URL senza http://o www? Funzionerà con questo tipo di URL?
Nathan,

2
Ho provato a modificare il post originale per risolvere il problema mailto, ma devo aggiungere almeno 6 caratteri per effettuare una modifica. Ma se cambi questa riga: replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;con questo replacePattern3 = /(\w+@[a-zA-Z_]+?(\.[a-zA-Z]{2,6})+)/gim;risolve il problema mailto :)
yourdeveloperfriend

70

Ho apportato alcune ottimizzazioni al Linkify()codice di Travis sopra. Ho anche corretto un bug in cui gli indirizzi e-mail con formati di tipo sottodominio non sarebbero stati trovati (ad esempio esempio@dominio.co.uk).

Inoltre, ho modificato l'implementazione per prototipare la Stringclasse in modo che gli articoli possano essere abbinati in questo modo:

var text = 'address@example.com';
text.linkify();

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

Comunque, ecco la sceneggiatura:

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

Il migliore secondo me, dato che le funzioni del prototipo rendono le cose molto più pulite :)
MRVDOG

sembra che non funzioni con tali indirizzi di posta elettronica: info@some-thing.com some.thing@example.com ecc.
Marco Gagliardi

@MarcoGagliardi Buona cattura. Fisso.
Roshambo,

1
Questo non funziona per la stringa "git clone aaaa@bitbucket.org/ooo/bbb-cc-dd.git ". Ha spezzato la stringa in pezzi e creato più ancore come questo "clone git <a href="https://<a href="mailto:aaaa@bitbucket.org"> aaaa@bitbucket.org </a> / ooo / bbb-cc-dd.git "> https: // <a href="mailto:aaaa@bitbucket.org"> aaaa@bitbucket.org </a> /ooo/bbb-cc-dd.git </a> "
Jebin,

1
Non funziona con +nomi utente e-mail, ad esempio foo+bar@domain.com. L'ho risolto con il modello di email /[\w.+]+@[a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim(nota +tra le prime parentesi), ma non so se questo rompe qualcos'altro.
Dchacke

24

Grazie, è stato molto utile. Volevo anche qualcosa che collegasse cose che sembravano un URL - come requisito di base, avrebbe collegato qualcosa come www.yahoo.com, anche se il prefisso del protocollo http: // non era presente. Quindi, fondamentalmente, se "www". è presente, lo collegherà e supporrà che sia http: //. Volevo anche che le e-mail si trasformassero in mailto: links. ESEMPIO: www.yahoo.com verrebbe convertito in www.yahoo.com

Ecco il codice con cui sono finito (combinazione di codice da questa pagina e altre cose che ho trovato online e altre cose che ho fatto da solo):

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
}

Nella seconda sostituzione, la parte (^ | [^ /]) sostituisce www.whatever.com solo se non è già preceduto da // - per evitare il doppio collegamento se un URL era già collegato nella prima sostituzione. Inoltre, è possibile che www.whatever.com sia all'inizio della stringa, che è la prima condizione "o" in quella parte del regex.

Questo potrebbe essere integrato come plug-in jQuery come Jesse P illustrato sopra, ma in particolare volevo una funzione regolare che non agiva su un elemento DOM esistente, perché sto prendendo il testo che ho e quindi aggiungendolo al DOM, e Voglio che il testo sia "collegato" prima di aggiungerlo, quindi passo il testo attraverso questa funzione. Funziona alla grande.


1
C'è un problema con il 2o modello, che corrisponde al semplice "www.domain.com" da solo. Il problema si verifica quando l'URL contiene una sorta di referrer, come: & 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 - nel qual caso il collegamento si ricollegherà automaticamente. Una soluzione rapida è aggiungere il carattere "f" dopo l'elenco negato che contiene "/". Quindi l'espressione è: replacePattern2 = /
^|[

Il codice sopra fallirà molti test per casi limite. Quando si rilevano gli URL, è meglio fare affidamento su una libreria specializzata. Ecco perché .
Dan Dascalescu,

2
Ho appena eseguito su una stringa in cui alcuni dei collegamenti Web hanno già un collegamento href su di essi. In questo caso non riesce a incasinare i collegamenti di lavoro esistenti.
AdamJones,

17

Identificare gli URL è complicato perché sono spesso circondati da segni di punteggiatura e perché gli utenti spesso non usano la forma completa dell'URL. Esistono molte funzioni JavaScript per la sostituzione di URL con collegamenti ipertestuali, ma non sono riuscito a trovarne uno che funzioni così come il urlizefiltro nel framework Web basato su Python Django. Ho quindi portato la urlizefunzione di Django su JavaScript:

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

Un esempio:

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

Il secondo argomento, se vero, fa sì rel="nofollow"che venga inserito. Il terzo argomento, se vero, sfugge ai caratteri che hanno un significato speciale in HTML. Vedi il file README .


Funziona anche con sorgente html come: www.web.com <a href = "https: // github. Com"> url </ a> del testo
Paulius Zaliaduonis

@Paulius: se imposti l'opzione django_compatiblesu false, gestirà un po 'meglio quel caso d'uso.
Vebjorn Ljosa,

Django urlizenon supporta correttamente i TLD (almeno non la porta JS su GitHub). Una libreria che gestisce correttamente i TLD è Linkify JavaScript di Ben Alman .
Dan Dascalescu,

È stato aggiunto il supporto per il rilevamento di URL con domini di primo livello aggiuntivi anche quando l'URL non inizia con "http" o "www".
Vebjorn Ljosa,

10

Ho apportato una modifica a Roshambo String.linkify () a emailAddressPattern per riconoscere gli indirizzi 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>');
    };
}

Il codice sopra fallirà molti test per casi limite. Quando si rilevano gli URL, è meglio fare affidamento su una libreria specializzata. Ecco perché .
Dan Dascalescu,

9

Ho cercato su Google qualcosa di nuovo e mi sono imbattuto in questo:

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

demo: http://jsfiddle.net/kachibito/hEgvc/1/

Funziona davvero bene per i normali collegamenti.


Che cosa sono i "collegamenti normali" qui? Guarda il fork della tua demo qui: jsfiddle.net/hEgvc/27 Le persone verrebbero coperte e scoperte in modo semplice. L'URI non è una cosa facile come da RFC3986 e se desideri coprire solo "Link normali", ti suggerisco di seguire almeno questa regexp: ^ (([^: /? #] +):)? (// ([ ^ /? #] *))? ([^? #] *) (\? ([^ #] *))? (# (. *))?
Ivan

2
Intendevo qualsiasi cosa nel formato http://example.com/folder/folder/folder/o https://example.org/blahecc., Solo il tipico formato URL non pazzo che corrisponderà al 95-99% dei casi d'uso là fuori. Sto usando questo per un'area amministrativa interna, quindi non ho bisogno di niente di speciale per catturare casi limite o hashlink.
degenerato il


5

Questa soluzione funziona come molte delle altre e in effetti utilizza la stessa regex di una di esse, tuttavia invece di restituire una stringa HTML questo restituirà un frammento di documento contenente l'elemento A e tutti i nodi di testo applicabili.

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

Ci sono alcuni avvertimenti, vale a dire con IE più vecchio e supporto textContent.

ecco una demo.


2
@DanDascalescu Invece di effettuare il downvoting generale del lotto, è possibile fornire i casi limite.
rlemon,

Ho bisogno di? Dai un'occhiata al regexp Component per gli URL . Ma se insisti, corri contro la suite di test linkify di Ben Alman . Ho iniziato a contribuire a test falliti, ad esempio per urlize , ma presto mi sono reso conto che vale la pena farlo solo per seri sforzi in biblioteca. Con tutto il dovuto rispetto, quella sopra è una risposta StackOverflow, non una libreria di provenienza aperta che tenta di analizzare correttamente gli URL.
Dan Dascalescu,

2
quindi ci sono casi limite. meraviglioso. queste risposte possono ancora essere utili agli altri e il downvoting generale sembra eccessivo. Le altre risposte che hai commentato e apparentemente downvoted do contenere informazioni utili (così come la risposta). non tutti si scontreranno con questi casi e non tutti vorranno usare una biblioteca.
rlemon,

Esattamente. Coloro che non comprendono i limiti della regexps sono quelli che scremeranno felicemente la prima regexp dalla risposta più votata e correranno con essa. Quelle sono le persone che dovrebbero usare di più le biblioteche.
Dan Dascalescu,

1
Ma come è giustificata questa giustificazione per votare in negativo ogni risposta con soluzioni non-preferite-preferite?
rlemon

4

Se devi mostrare un collegamento più breve (solo dominio), ma con lo stesso URL lungo, puoi provare la mia modifica della versione del codice di Sam Hasler pubblicata sopra

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

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

Di seguito sono riportate alcune stringhe testate:

  1. Trovami su www.google.com
  2. www
  3. Trovami su www. http://www.com
  4. Seguimi su: http://www.nishantwork.wordpress.com
  5. http://www.nishantwork.wordpress.com
  6. Seguimi su: http://www.nishantwork.wordpress.com
  7. https://stackoverflow.com/users/430803/nishant

Nota: se non si desidera passare wwwcome valido, basta usare sotto reg ex: /(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig


Il codice sopra fallirà molti test per casi limite. Quando si rilevano gli URL, è SEMPRE meglio fare affidamento su una libreria specializzata. Ecco perché .
Dan Dascalescu,

3

Gli avvertimenti sulla complessità dell'URI devono essere annotati, ma la semplice risposta alla tua domanda è:
per sostituire ogni corrispondenza devi aggiungere il /gflag alla fine di RegEx:
/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi


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

semplice esempio


2

Keep it simple! Di 'quello che non puoi avere, piuttosto che quello che puoi avere :)

Come accennato in precedenza, gli URL possono essere piuttosto complessi, soprattutto dopo il "?", E non tutti iniziano con un "www". per esempiomaps.bing.com/something?key=!"£$%^*()&lat=65&lon&lon=20

Quindi, piuttosto che avere una regex complessa che non soddisferà tutti i casi limite e sarà difficile da mantenere, che ne dici di questo molto più semplice, che funziona bene per me in pratica.

Incontro

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

www. (anything but a space)+

Dove "tutto" è [^'"<>\s] ... fondamentalmente una partita golosa, continuando a incontrarti con uno spazio, una citazione, una parentesi angolare o una fine della linea

Anche:

Ricorda di verificare che non sia già in formato URL, ad es. Il testo contiene href="..."osrc="..."

Aggiungi ref = nofollow (se appropriato)

Questa soluzione non è "buona" come le librerie sopra menzionate, ma è molto più semplice e funziona bene nella pratica.

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;

2

Il corretto rilevamento degli URL con domini internazionali e supporto di caratteri astrali non è cosa da poco. linkify-itla libreria crea regex da molte condizioni e la dimensione finale è di circa 6 kilobyte :). È più preciso di tutte le librerie, attualmente indicato nella risposta accettata.

Guarda la demo di linkify-it per controllare dal vivo tutti i casi limite e testarli.

Se è necessario collegare l'origine HTML, è necessario prima analizzarlo e iterare ogni token di testo separatamente.



0

Ho dovuto fare il contrario e creare collegamenti HTML solo nell'URL, ma ho modificato la tua regex e funziona come un incantesimo, grazie :)

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

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

Non vedo il punto della tua regex. Abbina tutto sostituendo tutto con tutto. In effetti il ​​tuo codice non fa nulla.
Chad Grant,

8
Immagino che dovrei aspettare di commentare per consentire alle persone di completare la modifica. scusa.
Chad Grant,

0

Il rilevamento e-mail nella risposta di Travitron sopra non ha funzionato per me, quindi l'ho esteso / sostituito con il seguente (codice 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);

Ciò consente indirizzi e-mail come " firstname.secondname@one.two.three.co.uk ".


Il codice sopra fallirà molti test per casi limite. Quando si rilevano gli URL, è SEMPRE meglio fare affidamento su una libreria specializzata. Ecco perché .
Dan Dascalescu,

Grazie, @DanDascalescu Di solito, è sempre meglio generalizzare eccessivamente.
Uwe Keim,

0

Dopo l'input da diverse fonti, ora ho una soluzione che funziona bene. Ha a che fare con la scrittura del proprio codice di sostituzione.

Risposta .

Violino .

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

2
Il codice sopra (e la maggior parte delle espressioni regolari in generale) fallirà molti test per i casi limite. Quando si rilevano gli URL, è meglio fare affidamento su una libreria specializzata. Ecco perché .
Dan Dascalescu,

Dan, esiste una biblioteca del genere? Anche se in questo caso dovremmo comunque abbinare la regex sopra in modo che il codice non possa mai generare immondizia quando qualcosa di simile all'immondizia (anche se un'altra libreria certifica l'immondizia come un URL / URI valido) viene utilizzato come input.
Mike Mestnik,


0

Ecco la mia soluzione:

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

0

Prova la seguente funzione:

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/"));


0

Prova sotto la soluzione

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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.