ejecutar - llamar una funcion javascript desde href
¿Cómo reemplazar URLs simples con enlaces? (21)
Reemplazo de URL con enlaces (Respuesta al problema general)
La expresión regular en la pregunta pierde muchos casos de borde. Al detectar URL, siempre es mejor usar una biblioteca especializada que maneje nombres de dominio internacionales, nuevos TLD como .museum
, paréntesis y otros signos de puntuación dentro y al final de la URL, y muchos otros casos de borde. Consulte la publicación del blog de Jeff Atwood parentheses para obtener una explicación de algunos de los otros problemas.
El mejor resumen de las bibliotecas de concordancia de URL está en la respuesta de Dan Dascalescu
(a partir de febrero de 2014)
"Haga 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.
Estoy usando la siguiente función para hacer coincidir las URL dentro de un texto dado 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 me di cuenta de 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>");
}
¡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''. por ejemplo, maps.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 de vanguardia y que sea difícil de mantener, ¿qué tal esto es mucho más simple, lo cual me funciona bien 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, continuando con un espacio, una cita, un corchete angular o un final de línea
También:
Recuerde verificar que no esté en formato URL, por ejemplo, el texto contiene href="..."
o src="..."
Agregue ref = nofollow (si es apropiado)
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;
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;
}
}
Busqué en Google algo más nuevo y encontré esto:
$(''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.
Después de la entrada de varias fuentes ahora tengo una solución que funciona bien. Tenía que ver con escribir tu propio código de reemplazo.
Answer
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;
});
}
El mejor script para hacer esto: http://benalman.com/projects/javascript-linkify-process-lin/
En primer lugar, rodar su propia expresión regular para analizar URL es una idea terrible . Debes imaginar que este es un problema bastante común que alguien ha escrito, depurado y tested una biblioteca, de acuerdo con los RFC . Los URI son complejos : verifique el código para el análisis de URL en Node.js y la página de Wikipedia en esquemas de URI .
Hay un montón de casos de vanguardia cuando se trata de analizar URL: nombres de dominio internacionales, TLD reales ( .museum
) vs. inexistentes ( .etc
), puntuación extraña, incluidos parentheses , puntuación al final de la URL, nombres de host de IPV6, etc.
He visto un montón de libraries , y hay algunas que vale la pena usar a pesar de algunas desventajas:
- linkify de Soapbox ha visto un gran esfuerzo, y un importante refactor en junio de 2015 eliminó la dependencia de jQuery . Todavía tiene problemas con los IDNs .
- AnchorMe es un recién llegado que dice ser más rápido y más delgado. Algunos problemas de IDN también.
- Autolinker.js enumera características muy específicamente (por ejemplo, " Autolinker.js correctamente la entrada HTML. La utilidad no cambiará el atributo
href
dentro de las etiquetas anchor ()" ). Le haré algunas pruebas cuando esté disponible una demostración .
Bibliotecas que he descalificado rápidamente para esta tarea:
- La urlize de Django no manejó ciertos TLD correctamente (aquí está la lista oficial de TLD válidos . No hay demo .
- autolink-js no detectaría "www.google.com" sin http: //, por lo que no es muy adecuado para el enlace automático de "URL casuales" (sin un esquema / protocolo) que se encuentran en texto sin formato.
- El enlace de Ben Alman no se ha mantenido desde 2009.
Si insiste en una expresión regular, la más completa es la expresión regular de URL de Component , aunque detectará falsamente algunos TLD de dos letras que no existen al mirarlos.
Escribí otra biblioteca de JavaScript, podría ser mejor para usted ya que es muy sensible con los falsos positivos menos posibles, rápidos y de tamaño pequeño. Actualmente lo estoy manteniendo activamente, así que, por favor, pruébelo AnchorMe y vea cómo funcionaría para usted.
Esta solución funciona como muchas de las otras, y de hecho utiliza 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 cualquier nodo de texto aplicable.
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 compatibilidad con IE y textContent anteriores.
here hay una demo.
Gracias, esto fue muy útil. También quería algo que vinculara cosas que parecían una URL: como requisito básico, enlazaría algo como www.yahoo.com, incluso si el prefijo de protocolo http: // no estuviera presente. Así que 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 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 la segunda sustitución, la parte (^ | [^ /]) solo reemplaza a www.whatever.com si aún no tiene el prefijo // - para evitar la doble vinculación si una URL ya estaba vinculada en la primera sustitución. Además, es posible que www.whatever.com esté al principio 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 de jQuery como lo ilustra Jesse P, pero específicamente quería una función normal que no actuaba en un elemento DOM existente, porque estoy tomando el texto que tengo y luego lo agrego al DOM, y Quiero que el texto esté "vinculado" antes de agregarlo, así que paso el texto a través de esta función. Funciona genial.
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;
}
Hice un cambio en Roshambo String.linkify () en el emailAddressPattern para reconocer aaa.bbb. @ Ccc.ddd address
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>'');
};
}
La detección correcta de URL con dominios internacionales y compatibilidad con caracteres astrales no es algo trivial. linkify-it
biblioteca linkify-it
construye linkify-it
regulares desde muchas condiciones , y el tamaño final es de aproximadamente 6 kilobytes :). Es más preciso que todas las libretas, actualmente referenciadas en la respuesta aceptada.
Vea la markdown-it.github.io/linkify-it para ver en vivo todos los casos de borde y probar sus casos.
Si necesita vincular la fuente HTML, primero debe analizarla e iterar cada token de texto por separado.
La detección de correo electrónico en la respuesta anterior de Travitron no funcionó para mí, así que lo extendí / reemplazé con el 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] ".
La identificación de las URL es complicada 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 URL con hipervínculos, pero no pude encontrar una que funcione tan bien como el filtro urlize
en el marco web basado en Python Django. Por lo tanto, urlize
función urlize
de Django a JavaScript:
Un ejemplo:
urlize(''Go to SO (.com) and ask. <grin>'',
{nofollow: true, autoescape: true})
=> "Go to SO (<a href="http://.com" rel="nofollow">.com</a>) and ask. <grin>"
El segundo argumento, si es verdadero, hace que se inserte rel="nofollow"
. El tercer argumento, si es verdadero, escapa a los caracteres que tienen un significado especial en HTML. Ver el archivo README .
Las advertencias sobre la complejidad de URI deben anotarse, pero la respuesta simple a su pregunta es:
Para reemplazar todas las coincidencias, debe agregar el indicador /g
al final de RegEx:
/(/b(https?|ftp|file):////[-A-Z0-9+&@#//%?=~_|!:,.;]*[-A-Z0-9+&@#//%=~_|])/gi
Reemplace las URL en el texto con enlaces HTML, ignore las URL dentro de una etiqueta href / pre. https://github.com/JimLiu/auto-link
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>");
}
Tuve que hacer lo contrario, y hacer enlaces html solo en la URL, pero modifiqué tu expresión regular y funciona como un encanto, gracias :)
var exp = /<a/s.*href=[''"](/b(https?|ftp|file):////[-A-Z0-9+&@#//%?=~_|!:,.;]*[-A-Z0-9+&@#//%=~_|])[''"].*>.*<//a>/ig; source = source.replace(exp,"$1");
Linkify()
algunas optimizaciones al código Linkify()
Travis arriba. También corregí 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 crear un prototipo de la clase String
para que los elementos se puedan comparar de la siguiente manera:
var text = ''[email protected]'';
text.linkify();
''http://.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>'');
};
}
Reg. Ej .: /(/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 muestran algunas cadenas de prueba:
- Encuéntrame en www.google.com
- www
- Encuéntrame en www. http://www.com
- Sígueme en: http://www.nishantwork.wordpress.com
- http://www.nishantwork.wordpress.com
- Sígueme en: http://www.nishantwork.wordpress.com
- https://.com/users/430803/nishant
Nota: Si no quiere pasar www
como válido, solo use el siguiente registro ej .: /(/b((https?|ftp|file):////|(www))[-A-Z0-9+&@#//%?=~_|!:,.;]*[-A-Z0-9+&@#//%=~_|])/ig