Detectar URL en texto con JavaScript

151

¿Alguien tiene sugerencias para detectar URL en un conjunto de cadenas?

arrayOfStrings.forEach(function(string){
  // detect URLs in strings and do something swell,
  // like creating elements with links.
});

Actualización: Terminé usando esta expresión regular para la detección de enlaces ... Aparentemente, varios años después.

kLINK_DETECTION_REGEX = /(([a-z]+:\/\/)?(([a-z0-9\-]+\.)+([a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|local|internal))(:[0-9]{1,5})?(\/[a-z0-9_\-\.~]+)*(\/([a-z0-9_\-\.]*)(\?[a-z0-9+_\-\.%=&]*)?)?(#[a-zA-Z0-9!$&'()*+.=-_~:@/?]*)?)(\s+|$)/gi

El asistente completo (con soporte opcional para manillares) está en la esencia # 1654670 .

Arbales
fuente
11
Probablemente no sea una buena idea tratar de enumerar un conjunto finito de TLD, ya que siguen creando nuevos.
Maxy-B
De acuerdo. A veces necesitamos un código que se pueda actualizar con TLD. En realidad, se puede construir un script para agregar TLD a expresiones regulares o TLD de actualización de código dinámico en el código. Hay cosas en la vida que deben estandarizarse como TLD y Timezone. El control finito podría ser bueno para verificar la URL verificable "TLD" existente para el caso de uso de la dirección del mundo real.
Edward Chan JW

Respuestas:

217

Primero necesitas una buena expresión regular que coincida con las URL. Esto es dificil de hacer. Mira aquí , aquí y aquí :

... casi cualquier cosa es una URL válida. Hay algunas reglas de puntuación para dividirlo. En ausencia de cualquier puntuación, todavía tiene una URL válida.

Verifique el RFC cuidadosamente y vea si puede construir una URL "no válida". Las reglas son muy flexibles.

Por ejemplo, :::::es una URL válida. El camino es ":::::". Un nombre de archivo bastante estúpido, pero un nombre de archivo válido.

Además, /////es una URL válida. El netloc ("nombre de host") es "". El camino es "///". De nuevo, estúpido. También valido. Esta URL normaliza a "///" cuál es el equivalente.

Algo así "bad://///worse/////" es perfectamente válido. Tonta pero válida.

De todos modos, esta respuesta no está destinada a darle la mejor expresión regular, sino más bien una prueba de cómo hacer que la cadena se ajuste dentro del texto, con JavaScript.

OK, así que usemos este: /(https?:\/\/[^\s]+)/g

Nuevamente, esta es una mala expresión regular . Tendrá muchos falsos positivos. Sin embargo, es lo suficientemente bueno para este ejemplo.

function urlify(text) {
  var urlRegex = /(https?:\/\/[^\s]+)/g;
  return text.replace(urlRegex, function(url) {
    return '<a href="' + url + '">' + url + '</a>';
  })
  // or alternatively
  // return text.replace(urlRegex, '<a href="$1">$1</a>')
}

var text = 'Find me at http://www.example.com and also at http://stackoverflow.com';
var html = urlify(text);

console.log(html)

// html now looks like:
// "Find me at <a href="http://www.example.com">http://www.example.com</a> and also at <a href="http://stackoverflow.com">http://stackoverflow.com</a>"

Entonces, en resumen, intente:

$$('#pad dl dd').each(function(element) {
    element.innerHTML = urlify(element.innerHTML);
});
Creciente Fresco
fuente
44
Algunos ejemplos de los "muchos falsos positivos" mejorarían en gran medida esta respuesta. De lo contrario, los futuros Googlers se quedan con algunos (¿tal vez válidos?) FUD.
cmcculloh
Nunca supe que puede pasar la función como segundo parámetro para .replace: |
Aamir Afridi
44
Es bueno, pero hace lo "incorrecto" con text="Find me at http://www.example.com, and also at http://stackoverflow.com."resultados de puntuación finales en dos 404. Algunos usuarios son conscientes de esto y agregarán un espacio después de las URL antes de la puntuación para evitar la rotura, pero la mayoría de los vinculadores que uso (Gmail, etherpad, phabricator) separan la puntuación final de la URL.
skierpage
En caso de que el texto ya contenga una URL anclada, puede usar la función removeAnchors (text) {var div = $ ('<div> </div>') .html (text); div.find ('a'). contenido (). unwrap (); return div.text (); } para eliminar primero los anclajes antes de devolver text.replace
Muneeb Mirza
Si el texto ya contiene una URL anclada, está usando jquery para eliminar el ancla, pero estoy usando Angular. ¿Cómo puedo quitar el ancla en Angular?
Sachin Jagtap
132

Esto es lo que terminé usando como mi expresión regular:

var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;

Esto no incluye la puntuación final en la URL. La función de Crescent funciona de maravilla :) así que:

function linkify(text) {
    var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
    return text.replace(urlRegex, function(url) {
        return '<a href="' + url + '">' + url + '</a>';
    });
}
Niaz Mohammed
fuente
44
¡Finalmente una expresión regular que realmente funciona en el caso más obvio! Este merece un marcador. Probé miles de ejemplos de búsqueda de Google hasta que encontré esto.
Ismael
66
Simple y agradable! Pero el urlRegexdebe definirse afuera linkify como compilarlo es costoso.
BM
1
Esto no puede detectar la URL completa: disney.wikia.com/wiki/Pua_(Moana)
Jry9972
1
Agregué ()en cada lista de personajes y funciona ahora.
Guillaume F.
3
no puede detectar una URL que comienza con solo www. por ejemplo: www.facebook.com
CraZyDroiD
51

Busqué en Google este problema durante bastante tiempo, luego se me ocurrió que hay un método de Android, android.text.util.Linkify, que utiliza algunas expresiones regulares bastante robustas para lograr esto. Afortunadamente, Android es de código abierto.

Utilizan algunos patrones diferentes para hacer coincidir diferentes tipos de URL. Puedes encontrarlos todos aquí: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.0_r1/android/text/util/Regex.java#Regex. 0WEB_URL_PATTERN

Si solo le preocupan las URL que coinciden con WEB_URL_PATTERN, es decir, las URL que se ajustan a la especificación RFC 1738, puede usar esto:

/((?:(http|https|Http|Https|rtsp|Rtsp):\/\/(?:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,64}(?:\:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,25})?\@)?)?((?:(?:[a-zA-Z0-9][a-zA-Z0-9\-]{0,64}\.)+(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnrwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eouw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw]))|(?:(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])))(?:\:\d{1,5})?)(\/(?:(?:[a-zA-Z0-9\;\/\?\:\@\&\=\#\~\-\.\+\!\*\'\(\)\,\_])|(?:\%[a-fA-F0-9]{2}))*)?(?:\b|$)/gi;

Aquí está el texto completo de la fuente:

"((?:(http|https|Http|Https|rtsp|Rtsp):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
+ "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
+ "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
+ "((?:(?:[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}\\.)+"   // named host
+ "(?:"   // plus top level domain
+ "(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
+ "|(?:biz|b[abdefghijmnorstvwyz])"
+ "|(?:cat|com|coop|c[acdfghiklmnoruvxyz])"
+ "|d[ejkmoz]"
+ "|(?:edu|e[cegrstu])"
+ "|f[ijkmor]"
+ "|(?:gov|g[abdefghilmnpqrstuwy])"
+ "|h[kmnrtu]"
+ "|(?:info|int|i[delmnoqrst])"
+ "|(?:jobs|j[emop])"
+ "|k[eghimnrwyz]"
+ "|l[abcikrstuvy]"
+ "|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])"
+ "|(?:name|net|n[acefgilopruz])"
+ "|(?:org|om)"
+ "|(?:pro|p[aefghklmnrstwy])"
+ "|qa"
+ "|r[eouw]"
+ "|s[abcdeghijklmnortuvyz]"
+ "|(?:tel|travel|t[cdfghjklmnoprtvwz])"
+ "|u[agkmsyz]"
+ "|v[aceginu]"
+ "|w[fs]"
+ "|y[etu]"
+ "|z[amw]))"
+ "|(?:(?:25[0-5]|2[0-4]" // or ip address
+ "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(?:25[0-5]|2[0-4][0-9]"
+ "|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1]"
+ "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
+ "|[1-9][0-9]|[0-9])))"
+ "(?:\\:\\d{1,5})?)" // plus option port number
+ "(\\/(?:(?:[a-zA-Z0-9\\;\\/\\?\\:\\@\\&\\=\\#\\~"  // plus option query params
+ "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
+ "(?:\\b|$)";

Si quieres ser realmente elegante, también puedes probar las direcciones de correo electrónico. La expresión regular para las direcciones de correo electrónico es:

/[a-zA-Z0-9\\+\\.\\_\\%\\-]{1,256}\\@[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}(\\.[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25})+/gi

PD: Los dominios de nivel superior admitidos por expresiones regulares anteriores están vigentes a partir de junio de 2007. Para obtener una lista actualizada, deberá consultar https://data.iana.org/TLD/tlds-alpha-by-domain.txt .

Adán
fuente
3
Como tiene una expresión regular que no distingue entre mayúsculas y minúsculas, no tiene que especificar a-zA-Zy http|https|Http|Https|rtsp|Rtsp.
Ry-
44
Esto es bueno, pero no estoy seguro de si alguna vez lo usaría. Para la mayoría de los casos de uso, prefiero aceptar algunos falsos positivos que utilizar un enfoque que se base en una lista codificada de TLD. Si incluye TLD en su código, está garantizando que algún día quedará obsoleto, y preferiría no incluir mantenimiento obligatorio futuro en mi código si puedo evitarlo.
Mark Amery
3
Esto funciona el 101% del tiempo, desafortunadamente también encuentra URL que no están precedidas por un espacio. Si ejecuto una coincidencia en [email protected], atrapa 'mydomain.com'. ¿Hay alguna manera de mejorar esto para atraparlo solo si tiene un espacio antes?
Deminetix
También para tener en cuenta, esto es perfecto para atrapar las URL ingresadas por los usuarios
Deminetix
Tenga en cuenta que grepcode.com ya no está activo, esto es lo que creo que es un enlace al lugar correcto en el código fuente de Android. Creo que la expresión regular que usa Android podría actualizarse desde 2013 (publicación original), pero no parece haberse actualizado desde 2015 y, por lo tanto, es posible que falten algunos TLD más nuevos.
James
19

Basado en la respuesta Crescent Fresh

si desea detectar enlaces con http: // O sin http: // y por www. puedes usar lo siguiente

function urlify(text) {
    var urlRegex = /(((https?:\/\/)|(www\.))[^\s]+)/g;
    //var urlRegex = /(https?:\/\/[^\s]+)/g;
    return text.replace(urlRegex, function(url,b,c) {
        var url2 = (c == 'www.') ?  'http://' +url : url;
        return '<a href="' +url2+ '" target="_blank">' + url + '</a>';
    }) 
}
h0mayun
fuente
Esta es una buena solución, pero también quiero comprobar que el texto no debería contener href. Intenté esta expresión regular = /((?!href)((https?:\/\/)|(www\.)|(mailto:))[^\sfont>+)/gi pero no funciona. ¿Me pueden ayudar o por qué la expresión regular anterior no funciona?
Sachin Jagtap
Me gusta que también hayas agregado target = "_ blank" a la salida devuelta. Esta versión es lo que quería. Nada demasiado exagerado (de lo contrario, usaría Linkifyjs) lo suficiente para obtener la mayoría de los enlaces.
Michael Kubler
18

Parece que esta biblioteca en NPM es bastante completa https://www.npmjs.com/package/linkifyjs

Linkify es un complemento de JavaScript pequeño pero completo para encontrar URL en texto plano y convertirlas en enlaces HTML. Funciona con todas las URL y direcciones de correo electrónico válidas.

Dan Kantor
fuente
44
Acabo de terminar de implementar linkifyjs en mi proyecto y es fantástico. Linkifyjs debería ser la respuesta a esta pregunta. El otro para ver es github.com/twitter/twitter-text
Uber Schnoz
6

La función también se puede mejorar para representar imágenes:

function renderHTML(text) { 
    var rawText = strip(text)
    var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;   

    return rawText.replace(urlRegex, function(url) {   

    if ( ( url.indexOf(".jpg") > 0 ) || ( url.indexOf(".png") > 0 ) || ( url.indexOf(".gif") > 0 ) ) {
            return '<img src="' + url + '">' + '<br/>'
        } else {
            return '<a href="' + url + '">' + url + '</a>' + '<br/>'
        }
    }) 
} 

o para una imagen en miniatura que se vincula a una imagen de tamaño completo:

return '<a href="' + url + '"><img style="width: 100px; border: 0px; -moz-border-radius: 5px; border-radius: 5px;" src="' + url + '">' + '</a>' + '<br/>'

Y aquí está la función strip () que procesa previamente la cadena de texto para lograr uniformidad al eliminar cualquier html existente.

function strip(html) 
    {  
        var tmp = document.createElement("DIV"); 
        tmp.innerHTML = html; 
        var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;   
        return tmp.innerText.replace(urlRegex, function(url) {     
        return '\n' + url 
    })
} 
Gautam Sharma
fuente
2
let str = 'https://example.com is a great site'
str.replace(/(https?:\/\/[^\s]+)/g,"<a href='$1' target='_blank' >$1</a>")

Short Code Big Work! ...

Resultado:-

 <a href="https://example.com" target="_blank" > https://example.com </a>
Kashan Haider
fuente
1

Hay un paquete npm existente: url-regex , simplemente instálelo con yarn add url-regexo npm install url-regexy úselo de la siguiente manera:

const urlRegex = require('url-regex');

const replaced = 'Find me at http://www.example.com and also at http://stackoverflow.com or at google.com'
  .replace(urlRegex({strict: false}), function(url) {
     return '<a href="' + url + '">' + url + '</a>';
  });
Vedmant
fuente
0

tmp.innerText no está definido. Deberías usar tmp.innerHTML

function strip(html) 
    {  
        var tmp = document.createElement("DIV"); 
        tmp.innerHTML = html; 
        var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;   
        return tmp.innerHTML .replace(urlRegex, function(url) {     
        return '\n' + url 
    })
Án Bình Trọng
fuente
0

prueba esto:

function isUrl(s) {
    if (!isUrl.rx_url) {
        // taken from https://gist.github.com/dperini/729294
        isUrl.rx_url=/^(?:(?:https?|ftp):\/\/)?(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$/i;
        // valid prefixes
        isUrl.prefixes=['http:\/\/', 'https:\/\/', 'ftp:\/\/', 'www.'];
        // taken from https://w3techs.com/technologies/overview/top_level_domain/all
        isUrl.domains=['com','ru','net','org','de','jp','uk','br','pl','in','it','fr','au','info','nl','ir','cn','es','cz','kr','ua','ca','eu','biz','za','gr','co','ro','se','tw','mx','vn','tr','ch','hu','at','be','dk','tv','me','ar','no','us','sk','xyz','fi','id','cl','by','nz','il','ie','pt','kz','io','my','lt','hk','cc','sg','edu','pk','su','bg','th','top','lv','hr','pe','club','rs','ae','az','si','ph','pro','ng','tk','ee','asia','mobi'];
    }

    if (!isUrl.rx_url.test(s)) return false;
    for (let i=0; i<isUrl.prefixes.length; i++) if (s.startsWith(isUrl.prefixes[i])) return true;
    for (let i=0; i<isUrl.domains.length; i++) if (s.endsWith('.'+isUrl.domains[i]) || s.includes('.'+isUrl.domains[i]+'\/') ||s.includes('.'+isUrl.domains[i]+'?')) return true;
    return false;
}

function isEmail(s) {
    if (!isEmail.rx_email) {
        // taken from http://stackoverflow.com/a/16016476/460084
        var sQtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]';
        var sDtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]';
        var sAtom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+';
        var sQuotedPair = '\\x5c[\\x00-\\x7f]';
        var sDomainLiteral = '\\x5b(' + sDtext + '|' + sQuotedPair + ')*\\x5d';
        var sQuotedString = '\\x22(' + sQtext + '|' + sQuotedPair + ')*\\x22';
        var sDomain_ref = sAtom;
        var sSubDomain = '(' + sDomain_ref + '|' + sDomainLiteral + ')';
        var sWord = '(' + sAtom + '|' + sQuotedString + ')';
        var sDomain = sSubDomain + '(\\x2e' + sSubDomain + ')*';
        var sLocalPart = sWord + '(\\x2e' + sWord + ')*';
        var sAddrSpec = sLocalPart + '\\x40' + sDomain; // complete RFC822 email address spec
        var sValidEmail = '^' + sAddrSpec + '$'; // as whole string

        isEmail.rx_email = new RegExp(sValidEmail);
    }

    return isEmail.rx_email.test(s);
}

También reconocerá URLs tales como google.com, http://www.google.bla, http://google.bla, www.google.blapero nogoogle.bla

kofifus
fuente
0

Puede usar una expresión regular como esta para extraer patrones de URL normales.

(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})

Si necesita patrones más sofisticados, use una biblioteca como esta.

https://www.npmjs.com/package/pattern-dreamer

Kang Andrew
fuente
¿Para qué sirve (?:www\.|(?!www))? ¿Por qué debería wwwww.comser inválido?
Toto
Tienes razón. En realidad solo lo tomé ya que muchos usan la expresión regular. Recomiendo usar la biblioteca vinculada de arriba. Deberíamos considerar muchos casos en la detección de URL, por lo que la expresión regular debería ser más complicada.
Kang Andrew
0

Solución orientada a objetos genérica

Para las personas como yo que usan marcos como angular que no permiten manipular DOM directamente, creé una función que toma una cadena y devuelve una matriz de url/ plainTextobjetos que se pueden usar para crear cualquier representación de UI que desee.

URL regex

Para la coincidencia de URL usé h0mayunregex (ligeramente adaptado) :/(?:(?:https?:\/\/)|(?:www\.))[^\s]+/g

Mi función también elimina los caracteres de puntuación desde el final de una URL como .y ,creo que con más frecuencia será una puntuación real que un final de URL legítimo (¡pero podría serlo! Esto no es ciencia rigurosa ya que otras respuestas explican bien) Para eso aplico el siguiente expresión regular en URL coincidentes /^(.+?)([.,?!'"]*)$/.

Código mecanografiado

    export function urlMatcherInText(inputString: string): UrlMatcherResult[] {
        if (! inputString) return [];

        const results: UrlMatcherResult[] = [];

        function addText(text: string) {
            if (! text) return;

            const result = new UrlMatcherResult();
            result.type = 'text';
            result.value = text;
            results.push(result);
        }

        function addUrl(url: string) {
            if (! url) return;

            const result = new UrlMatcherResult();
            result.type = 'url';
            result.value = url;
            results.push(result);
        }

        const findUrlRegex = /(?:(?:https?:\/\/)|(?:www\.))[^\s]+/g;
        const cleanUrlRegex = /^(.+?)([.,?!'"]*)$/;

        let match: RegExpExecArray;
        let indexOfStartOfString = 0;

        do {
            match = findUrlRegex.exec(inputString);

            if (match) {
                const text = inputString.substr(indexOfStartOfString, match.index - indexOfStartOfString);
                addText(text);

                var dirtyUrl = match[0];
                var urlDirtyMatch = cleanUrlRegex.exec(dirtyUrl);
                addUrl(urlDirtyMatch[1]);
                addText(urlDirtyMatch[2]);

                indexOfStartOfString = match.index + dirtyUrl.length;
            }
        }
        while (match);

        const remainingText = inputString.substr(indexOfStartOfString, inputString.length - indexOfStartOfString);
        addText(remainingText);

        return results;
    }

    export class UrlMatcherResult {
        public type: 'url' | 'text'
        public value: string
    }
eddyP23
fuente
0

Si desea detectar enlaces con http: // O sin http: // O ftp u otros casos posibles como eliminar la puntuación final al final, eche un vistazo a este código.

https://jsfiddle.net/AndrewKang/xtfjn8g3/

Una manera simple de usar eso es usar NPM

npm install --save url-knife
Kang Andrew
fuente