¿Cómo reemplazar las URL simples con enlaces?

454

Estoy usando la siguiente función para hacer coincidir las URL dentro de un texto determinado y reemplazarlas por enlaces HTML. La expresión regular está funcionando muy bien, pero actualmente solo estoy reemplazando la primera coincidencia.

¿Cómo puedo reemplazar toda la URL? Supongo que debería estar usando el comando exec , pero realmente no pensé cómo hacerlo.

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
fuente

Respuestas:

351

En primer lugar, rodar su propia expresión regular para analizar URL es una idea terrible . Debes imaginar que este es un problema lo suficientemente común como para que alguien haya escrito, depurado y probado una biblioteca, de acuerdo con los RFC . Los URI son complejos : consulte el código para el análisis de URL en Node.js y la página de Wikipedia sobre esquemas de URI .

Hay un montón de casos extremos cuando se trata de analizar URL: nombres de dominio internacionales, TLD reales ( .museum) vs. inexistentes ( .etc), puntuación extraña que incluye paréntesis , puntuación al final de la URL, nombres de host IPV6, etc.

He visto un montón de bibliotecas , y hay algunas que vale la pena usar a pesar de algunas desventajas:

Bibliotecas que he descalificado rápidamente para esta tarea:

Si insiste en una expresión regular, la más completa es la expresión regular de URL del Componente , aunque detectará falsamente algunos TLD de dos letras inexistentes al mirarla.

Dan Dascalescu
fuente
3
Es una pena URL regexp from Componentque no se comente, sería útil alguna explicación de lo que está haciendo. Autolinker.jsse comenta muy bien y tiene pruebas. La urlize.jsbiblioteca vinculada a la respuesta de Vebjorn Ljosa también parece funcional y bien mantenida, aunque no tiene pruebas.
Sam Hasler
1
Regex101.com automáticamente "explica" la expresión regular , pero buena suerte con eso :) También encontré rápidamente un caso de falla con un TLD no válido (mismo enlace).
Dan Dascalescu
1
@SamHasler: Autolinker necesita mejorar en el área de TLDs e IDNs. Se agregaron algunas pruebas .
Dan Dascalescu
2
Curioso de que nadie haya mencionado los esfuerzos de John Gruber para mantener un patrón de expresiones regulares de URL . No es la única solución / ideal para el problema, pero en cualquier caso vale la pena investigar, si está desarrollando su propia solución. Solo quería agregar esto como referencia.
oelna
2
@DanDascalescu Eche un vistazo a este markdown-it.github.io/linkify-it . Esta biblioteca se centra exactamente en una tarea: detectar patrones de enlace en el texto. Pero espero que lo haga bien. Por ejemplo, tiene soporte Unicode correcto, incluidos los caracteres astrales. Y es compatible con TLD internacionales.
Vitaly
285

Reemplazo de URL con enlaces (Respuesta al problema general)

La expresión regular en la pregunta pierde muchos casos extremos. Al detectar URL, siempre es mejor usar una biblioteca especializada que maneje nombres de dominio internacionales, nuevos TLD .museum, paréntesis y otros signos de puntuación dentro y al final de la URL, y muchos otros casos extremos. Consulte la publicación del blog de Jeff Atwood El problema con las URL para obtener una explicación de algunos de los otros problemas.

El mejor resumen de las bibliotecas de coincidencia de URL se encuentra en la Respuesta de Dan Dascalescu+100
(a partir de febrero de 2014)


"Hacer que una expresión regular reemplace más de una coincidencia" (Respuesta al problema específico)

Agregue una "g" al final de la expresión regular para habilitar la coincidencia global:

/ig;

Pero eso solo soluciona el problema en la pregunta donde la expresión regular solo reemplazaba la primera coincidencia. No uses ese código.

Sam Hasler
fuente
150

He hecho algunas pequeñas modificaciones al código de Travis (solo para evitar cualquier redeclaración innecesaria, pero está funcionando muy bien para mis necesidades, ¡qué buen trabajo!):

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
fuente
1
¿cómo editar el código no a los objetos y marcos flotantes daño incrustado .. (youtube objetos incrustados e iframes)
Pradyut Bhattacharya
55
Hay un error en el código que coincide con las direcciones de correo electrónico aquí. [a-zA-Z]{2,6}debería leer algo (?:[a-zA-Z]{2,6})+similar para coincidir con nombres de dominio más complicados, es decir, [email protected]
Roshambo
1
Me he encontrado con algunos problemas; primero solo http: // o http: // www (sin espacio www, incluso SO analiza este error aparentemente) creará un enlace. Y enlaces con http: // www. dominio com (sin espacios) creará un enlace vacío y luego uno con una etiqueta de cierre de anclaje adjunta en el campo href.
Alfred
1
¿Qué pasa con las URL sin http://o www? ¿Funcionará para ese tipo de URL?
Nathan
2
Traté de editar la publicación original para solucionar el problema de mailto, pero tengo que agregar al menos 6 caracteres para hacer una edición. Pero si cambia esta línea: replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;con esto replacePattern3 = /(\w+@[a-zA-Z_]+?(\.[a-zA-Z]{2,6})+)/gim;que soluciona el problema de mailto :)
yourdeveloperfriend
70

Hice algunas optimizaciones al Linkify()código de Travis arriba. También solucioné un error en el que las direcciones de correo electrónico con formatos de tipo de subdominio no coincidían (es decir, [email protected]).

Además, cambié la implementación para Stringcrear un prototipo de la clase, de modo que los elementos puedan coincidir así:

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

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

De todos modos, aquí está el guión:

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
fuente
Lo mejor en mi opinión, ya que las funciones de Prototype hacen las cosas mucho más limpias :)
MRVDOG
parece que no funciona con tales direcciones de correo electrónico: [email protected] [email protected] etc.
Marco Gagliardi
@MarcoGagliardi Buena captura. Fijo.
Roshambo
1
Esto no funciona para la cadena "git clone [email protected]/ooo/bbb-cc-dd.git ". Rompió la cadena en trozos y creó múltiples anclajes como este "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
No funciona con +nombres de usuario de correo electrónico, como [email protected]. Lo arreglé con el patrón de correo electrónico /[\w.+]+@[a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim(tenga +en cuenta los primeros corchetes), pero no sé si eso rompe algo más.
dchacke
24

Gracias, esto fue muy útil. También quería algo que vinculara cosas que parecían una URL; como requisito básico, vincularía algo como www.yahoo.com, incluso si el prefijo de protocolo http: // no estaba presente. Básicamente, si "www". está presente, lo vinculará y asumirá que es http: //. También quería que los correos electrónicos se convirtieran en mailto: enlaces. EJEMPLO: www.yahoo.com se convertiría a www.yahoo.com

Aquí está el código con el que terminé (combinación de código de esta página y otras cosas que encontré en línea, y otras cosas que hice por mi cuenta):

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
}

En el segundo reemplazo, la parte (^ | [^ /]) solo reemplaza www.whatever.com si aún no tiene el prefijo // - para evitar la doble vinculación si una URL ya estaba vinculada en el primer reemplazo. Además, es posible que www.whatever.com esté al comienzo de la cadena, que es la primera condición "o" en esa parte de la expresión regular.

Esto podría integrarse como un complemento jQuery como lo ilustra Jesse P arriba, pero específicamente quería una función regular que no actuara en un elemento DOM existente, porque estoy tomando el texto que tengo y luego lo agrego al DOM, y Quiero que el texto se "vincule" antes de agregarlo, así que paso el texto a través de esta función. Funciona genial.

Travis
fuente
1
Hay un problema con el segundo patrón, que coincide con "www.dominio.com" por sí solo. El problema existe cuando la URL tiene algún tipo de referencia, como: & 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, en cuyo caso el enlace se enlazó automáticamente nuevamente. Una solución rápida es agregar el carácter "f" después de la lista negada que contiene "/". Entonces, la expresión es: replacePattern2 = /(^|[^\/ffont>)(www\.[\Sfont>+(\b|$))/gim
Redtopia
El código anterior fallará en muchas pruebas para casos extremos. Al detectar URL, es mejor confiar en una biblioteca especializada. He aquí por qué .
Dan Dascalescu
2
Simplemente lo ejecuté en una cadena donde algunos de los enlaces web ya tienen enlaces href. En este caso, falla estropeando los enlaces de trabajo existentes.
AdamJones
17

Identificar las URL es complicado porque a menudo están rodeadas de signos de puntuación y porque los usuarios con frecuencia no usan la forma completa de la URL. Existen muchas funciones de JavaScript para reemplazar las URL con hipervínculos, pero no pude encontrar una que funcione tan bien como el urlizefiltro en el marco web basado en Python Django. Por lo tanto, porté la urlizefunción de Django a JavaScript:

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

Un ejemplo:

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

El segundo argumento, si es verdadero, hace rel="nofollow"que se inserte. El tercer argumento, si es verdadero, escapa a los caracteres que tienen un significado especial en HTML. Ver el archivo README .

Vebjorn Ljosa
fuente
También funciona con fuente html como: www.web.com <a href = "https: // github. Com"> url </ a> algún texto
Paulius Zaliaduonis
@Paulius: si configura la opción django_compatibleen falso, manejará ese caso de uso un poco mejor.
Vebjorn Ljosa
Django urlizeno admite TLD correctamente (al menos no el puerto JS en GitHub). Una biblioteca que maneja los TLD correctamente es JavaScript Linkify de Ben Alman .
Dan Dascalescu
Soporte para detectar URL con dominios de nivel superior adicionales incluso cuando la URL no comienza con "http" o "www" ha sido agregado.
Vebjorn Ljosa
10

Realicé un cambio en Roshambo String.linkify () a la dirección de correo electrónico Dirección para reconocer las direcciones 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
fuente
El código anterior fallará en muchas pruebas para casos extremos. Al detectar URL, es mejor confiar en una biblioteca especializada. He aquí por qué .
Dan Dascalescu
9

Busqué en Google algo nuevo y me encontré con este:

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

demostración: http://jsfiddle.net/kachibito/hEgvc/1/

Funciona muy bien para enlaces normales.

degenerar
fuente
¿Qué es "enlaces normales" aquí? Mire la bifurcación de su demo aquí: jsfiddle.net/hEgvc/27 La gente cubriría descubierta y lo haría de manera fácil. URI no es algo fácil según RFC3986 y si desea cubrir solo "Enlaces normales", le sugiero que siga esta expresión regular al menos: ^ (([^: /? #] +):)? (// ([ ^ /? #] *))? ([^? #] *) (\? ([^ #] *))? (# (. *))?
Ivan
2
Me refería a cualquier cosa en el formato http://example.com/folder/folder/folder/o https://example.org/blahetc., solo su típico formato de URL no loco que coincidirá con el 95-99% de los casos de uso. Estoy usando esto para un área administrativa interna, por lo que no necesito nada sofisticado para detectar casos límite o enlaces hash.
degenerar
5

Esta solución funciona como muchas de las otras, y de hecho usa la misma expresión regular que una de ellas, sin embargo, en lugar de devolver una Cadena HTML, devolverá un fragmento de documento que contiene el elemento A y los nodos de texto aplicables.

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

Hay algunas advertencias, a saber, con soporte para IE y textContent más antiguos.

Aquí hay una demostración.

rlemon
fuente
2
@DanDascalescu En lugar de hacer una votación general, el lote puede proporcionar dichos casos límite.
rlemon
¿Realmente necesito? Eche un vistazo a la expresión regular de componentes para las URL . Pero si insiste, corra contra el conjunto de pruebas de linkify de Ben Alman . Empecé a contribuir con las pruebas fallidas , por ejemplo, para urlize , pero pronto me di cuenta de que vale la pena hacerlo solo para los esfuerzos serios de la biblioteca. Con el debido respeto, la anterior es una respuesta de StackOverflow, no una biblioteca de código abierto que intenta analizar URL correctamente.
Dan Dascalescu
2
entonces hay casos extremos. maravilloso. Estas respuestas aún pueden ser útiles para los demás y votar en contra de ellas parece excesivo. Las otras respuestas que has comentado y aparentemente downvoted do contener información útil (así como su respuesta). no todos vendrán en contra de dichos casos, y no todos querrán usar una biblioteca.
rlemon
Exactamente. Aquellos que no entienden las limitaciones de las expresiones regulares son aquellos que felizmente leerán la primera expresión regular de la respuesta más votada y la ejecutarán. Esas son las personas que deberían usar más las bibliotecas.
Dan Dascalescu
1
Pero, ¿cómo es esa justificación para rechazar cada respuesta con expresiones regulares que no sean sus preferidas?
rlemon
4

Si necesita mostrar un enlace más corto (solo dominio), pero con la misma URL larga, puede probar mi modificación de la versión del código de Sam Hasler publicada anteriormente

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

A continuación se presentan algunas cadenas probadas:

  1. Encuéntrame en www.google.com
  2. www
  3. Encuéntrame en www. http://www.com
  4. Sígueme en: http://www.nishantwork.wordpress.com
  5. http://www.nishantwork.wordpress.com
  6. Sígueme en: http://www.nishantwork.wordpress.com
  7. https://stackoverflow.com/users/430803/nishant

Nota: Si no desea pasar wwwcomo válido solo use el siguiente reg ex: /(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig

Nishant Kumar
fuente
El código anterior fallará en muchas pruebas para casos extremos. Al detectar URL, SIEMPRE es mejor confiar en una biblioteca especializada. He aquí por qué .
Dan Dascalescu
3

Deben tenerse en cuenta las advertencias sobre la complejidad de URI, pero la respuesta simple a su pregunta es:
Para reemplazar cada coincidencia, debe agregar el /gindicador al final de RegEx:
/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi

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

ejemplo simple

Zuhair Taha
fuente
2

¡Mantenlo simple! Di lo que no puedes tener, en lugar de lo que puedes tener :)

Como se mencionó anteriormente, las URL pueden ser bastante complejas, especialmente después del '?', Y no todas comienzan con un 'www'. p.ejmaps.bing.com/something?key=!"£$%^*()&lat=65&lon&lon=20

Entonces, en lugar de tener una expresión regular compleja que no cumpla con todos los casos límite, y será difícil de mantener, ¿qué tal este mucho más simple, que funciona bien para mí en la práctica?

Partido

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

www. (anything but a space)+

Donde 'cualquier cosa' es [^'"<>\s] ... básicamente una coincidencia codiciosa, llevándote a un espacio, una cita, un ángulo o un final de línea

También:

Recuerde verificar que aún no esté en formato URL, por ejemplo, el texto contiene href="..."osrc="..."

Añadir ref = nofollow (si corresponde)

Esta solución no es tan "buena" como las bibliotecas mencionadas anteriormente, pero es mucho más simple y funciona bien en la práctica.

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
fuente
2

La detección correcta de URL con dominios internacionales y soporte de caracteres astrales no es algo trivial. linkify-itla biblioteca construye expresiones regulares desde muchas condiciones , y el tamaño final es de aproximadamente 6 kilobytes :). Es más preciso que todas las bibliotecas, actualmente se hace referencia en la respuesta aceptada.

Vea la demostración de linkify-it para ver en vivo todos los casos límite y probar los suyos.

Si necesita vincular la fuente HTML, primero debe analizarla e iterar cada token de texto por separado.

Vitalia
fuente
1

He escrito otra biblioteca de JavaScript, podría ser mejor para usted, ya que es muy sensible con los menos falsos positivos posibles, rápido y de tamaño pequeño. Actualmente lo estoy manteniendo activamente, así que pruébelo en la página de demostración y vea cómo funcionaría para usted.

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

Alex C.
fuente
Impresionante biblioteca. ¡Muchas gracias!
Serdar Değirmenci
0

Tuve que hacer lo contrario y hacer enlaces html solo en la URL, pero modifiqué su expresión regular y funciona de maravilla, gracias :)

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

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

fuente
No veo el punto de tu expresión regular. Combina todo reemplazando todo con todo. En efecto, su código no hace nada.
Chad Grant
8
Supongo que debería esperar para comentar para permitir que la gente termine de editar. lo siento.
Chad Grant
0

La detección de correo electrónico en la respuesta de Travitron anterior no funcionó para mí, por lo que la extendí / reemplacé con lo siguiente (código 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);

Esto permite direcciones de correo electrónico como " [email protected] ".

Uwe Keim
fuente
El código anterior fallará en muchas pruebas para casos extremos. Al detectar URL, SIEMPRE es mejor confiar en una biblioteca especializada. He aquí por qué .
Dan Dascalescu
Gracias, @DanDascalescu Por lo general, siempre es mejor generalizar en exceso.
Uwe Keim
0

Después de la entrada de varias fuentes, ahora tengo una solución que funciona bien. Tenía que ver con escribir su propio código de reemplazo.

Respuesta .

Violín .

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
fuente
2
El código anterior (y la mayoría de las expresiones regulares en general) fallará en muchas pruebas para casos extremos. Al detectar URL, es mejor confiar en una biblioteca especializada. He aquí por qué .
Dan Dascalescu
Dan, ¿hay tal biblioteca? Aunque en este caso todavía estaríamos haciendo coincidir la expresión regular anterior para que el código nunca pueda generar basura cuando algo como basura (incluso si otra biblioteca certifica la basura como una URL / URI válida) se utiliza como entrada.
Mike Mestnik el
0

Aquí está mi solución:

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
fuente
0

Pruebe la siguiente función:

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
fuente
0

Pruebe a continuación la solución

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
fuente