Bagaimana cara mengganti URL biasa dengan tautan?

454

Saya menggunakan fungsi di bawah ini untuk mencocokkan URL di dalam teks yang diberikan dan menggantinya dengan tautan HTML. Ekspresi reguler berfungsi dengan baik, tetapi saat ini saya hanya mengganti pertandingan pertama.

Bagaimana saya bisa mengganti semua URL? Saya kira saya harus menggunakan perintah exec , tapi saya tidak benar-benar mencari cara untuk melakukannya.

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
sumber

Jawaban:

351

Pertama, menggulirkan regexp Anda sendiri untuk mem-parsing URL adalah ide yang buruk . Anda harus membayangkan ini adalah masalah yang cukup umum bahwa seseorang telah menulis, men-debug dan menguji perpustakaan untuk itu, menurut RFC . URI rumit - lihat kode untuk parsing URL di Node.js dan halaman Wikipedia tentang skema URI .

Ada satu ton kasus tepi dalam hal mem-parsing URL: nama domain internasional , aktual ( .museum) vs tidak ada ( .etc) TLD, tanda baca aneh termasuk tanda kurung , tanda baca di akhir URL, nama host IPV6 dll.

Saya telah melihat satu ton dari perpustakaan , dan ada senilai beberapa menggunakan meskipun beberapa kelemahan:

Perpustakaan yang saya diskualifikasi dengan cepat untuk tugas ini:

Jika Anda bersikeras pada ekspresi reguler, yang paling komprehensif adalah regexp URL dari Component , meskipun itu akan mendeteksi beberapa TLD dua huruf yang tidak ada dengan melihatnya.

Dan Dascalescu
sumber
3
Sayang sekali URL regexp from Componenttidak berkomentar, beberapa penjelasan tentang apa yang dilakukannya akan sangat membantu. Autolinker.jsberkomentar dengan sangat baik dan memiliki tes. The urlize.jsperpustakaan terkait dalam jawaban Vebjorn Ljosa ini juga terlihat featureful dan terawat dengan baik, meskipun tidak memiliki tes.
Sam Hasler
1
Regex101.com secara otomatis "menjelaskan" regexp, tetapi semoga berhasil dengan itu :) Saya juga dengan cepat menemukan kasus kegagalan dengan TLD yang tidak valid (tautan yang sama).
Dan Dascalescu
1
@SamHasler: Autolinker perlu ditingkatkan di area TLD dan IDNs. Menambahkan beberapa tes .
Dan Dascalescu
2
Penasaran bahwa tidak ada yang menyebutkan upaya John Gruber dalam mempertahankan pola regex URL . Ini bukan satu-satunya / solusi ideal untuk masalah ini, tetapi dalam hal apa pun layak diselidiki, jika Anda menggulirkan solusi Anda sendiri. Hanya ingin menambahkan ini sebagai referensi.
oelna
2
@DanDascalescu Lihatlah ini markdown-it.github.io/linkify-it . Pustaka ini difokuskan tepat pada satu tugas - mendeteksi pola tautan dalam teks. Tapi saya harap, itu berhasil. Misalnya, ia memiliki dukungan unicode yang benar, termasuk karakter astral. Dan itu mendukung TLD internasional.
Vitaly
285

Mengganti URL dengan tautan (Jawab untuk Masalah Umum)

Ekspresi reguler dalam pertanyaan kehilangan banyak kasus tepi. Saat mendeteksi URL, selalu lebih baik menggunakan perpustakaan khusus yang menangani nama domain internasional, seperti TLD baru .museum, tanda kurung dan tanda baca lainnya di dalam dan di akhir URL, dan banyak kasus tepi lainnya. Lihat posting blog Jeff Atwood The Problem With URLs untuk penjelasan tentang beberapa masalah lainnya.

The Ringkasan terbaik dari perpustakaan pencocokan URL dalam Dan Dascalescu ini Jawaban+100
(per Feb 2014)


"Buat ekspresi reguler ganti lebih dari satu kecocokan" (Jawab untuk masalah tertentu)

Tambahkan "g" ke akhir ekspresi reguler untuk mengaktifkan pencocokan global:

/ig;

Tapi itu hanya memperbaiki masalah di pertanyaan di mana ekspresi reguler hanya menggantikan pertandingan pertama. Jangan gunakan kode itu.

Sam Hasler
sumber
150

Saya telah membuat beberapa modifikasi kecil pada kode Travis (hanya untuk menghindari deklarasi ulang yang tidak perlu - tetapi ini berfungsi baik untuk kebutuhan saya, pekerjaan yang sangat bagus!):

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
sumber
1
bagaimana cara mengedit kode ini agar tidak merusak objek dan iframe yang disematkan .. (youtube objek dan iframe yang disematkan)
Pradyut Bhattacharya
5
Ada bug dalam kode yang cocok dengan alamat email di sini. [a-zA-Z]{2,6}harus membaca sesuatu di sepanjang baris (?:[a-zA-Z]{2,6})+agar sesuai dengan nama domain yang lebih rumit, yaitu [email protected].
Roshambo
1
Saya mengalami beberapa masalah; pertama hanya http: // atau http: // www (tanpa ruang www bahkan SO mem-parsing kesalahan ini kelihatannya) akan membuat tautan. Dan tautan dengan http: // www. domain. com (tanpa spasi) akan membuat satu tautan kosong dan kemudian satu dengan tag penutup jangkar terlampir di bidang href.
Alfred
1
Bagaimana dengan URL tanpa http://atau www? Apakah ini akan berfungsi untuk URL semacam itu?
Nathan
2
Saya mencoba mengedit posting asli untuk memperbaiki masalah mailto, tetapi saya harus menambahkan setidaknya 6 karakter untuk melakukan pengeditan. Tetapi jika Anda mengubah baris ini: replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;dengan ini replacePattern3 = /(\w+@[a-zA-Z_]+?(\.[a-zA-Z]{2,6})+)/gim;yang memperbaiki masalah mailto :)
yourdeveloperfriend
70

Buat beberapa optimasi pada Linkify()kode Travis di atas. Saya juga memperbaiki bug di mana alamat email dengan format tipe subdomain tidak akan cocok (yaitu [email protected]).

Selain itu, saya mengubah implementasinya menjadi prototipe Stringkelas sehingga item dapat dicocokkan seperti:

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

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

Bagaimanapun, ini skripnya:

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
sumber
Yang terbaik menurut saya, karena fungsi Prototipe membuat semuanya jauh lebih bersih :)
MRVDOG
sepertinya tidak bekerja dengan alamat email seperti itu: [email protected] [email protected] dll.
Marco Gagliardi
@ MarscoGagliardi Tangkapan yang bagus. Tetap.
Roshambo
1
Ini tidak berfungsi untuk string "git clone [email protected]/ooo/bbb-cc-dd.git ". Itu memecah string menjadi potongan-potongan dan menciptakan beberapa jangkar seperti ini "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
Tidak berfungsi dengan +nama pengguna email, seperti [email protected]. Saya memperbaikinya dengan pola email /[\w.+]+@[a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim(perhatikan +di kurung pertama), tetapi saya tidak tahu apakah itu merusak sesuatu yang lain.
dchacke
24

Terima kasih, ini sangat membantu. Saya juga menginginkan sesuatu yang akan menautkan hal-hal yang tampak seperti URL - sebagai persyaratan dasar, itu akan menautkan sesuatu seperti www.yahoo.com, bahkan jika awalan http: // protokol tidak ada. Jadi pada dasarnya, jika "www." ada, itu akan menautkannya dan menganggap itu http: //. Saya juga ingin email berubah menjadi mailto: tautan. CONTOH: www.yahoo.com akan dikonversi ke www.yahoo.com

Inilah kode yang akhirnya saya dapatkan (kombinasi kode dari halaman ini dan hal-hal lain yang saya temukan online, dan hal-hal lain yang saya lakukan sendiri):

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
}

Di ganti ke-2, bagian (^ | [^ /]) hanya menggantikan www.wh whatever.com jika belum diawali oleh // - untuk menghindari penautan ganda jika URL sudah ditautkan pada penggantian pertama. Juga, mungkin saja www.wh whatever.com mungkin berada di awal string, yang merupakan kondisi "atau" pertama di bagian regex tersebut.

Ini dapat diintegrasikan sebagai plugin jQuery seperti yang diilustrasikan oleh Jesse P di atas - tetapi saya secara khusus menginginkan fungsi reguler yang tidak bekerja pada elemen DOM yang ada, karena saya mengambil teks yang saya miliki dan kemudian menambahkannya ke DOM, dan Saya ingin teks menjadi "ditautkan" sebelum saya menambahkannya, jadi saya meneruskan teks melalui fungsi ini. Bagus sekali.

Travis
sumber
1
Ada masalah dengan pola ke-2, yang cocok dengan "www.domain.com" dengan sendirinya. Masalahnya ada ketika url memiliki semacam pengarah di dalamnya, seperti: & 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 - dalam hal ini tautan otomatis ditautkan lagi. Perbaikan cepat adalah menambahkan karakter "f" setelah daftar negasi yang berisi "/". Jadi ungkapannya adalah: replacePattern2 = /(^|[^\/f[)(www#.[\S[+(\b|$))/gim
Redtopia
Kode di atas akan gagal banyak tes untuk kasus tepi. Saat mendeteksi URL, lebih baik mengandalkan perpustakaan khusus. Inilah sebabnya .
Dan Dascalescu
2
Saya hanya menjalankannya di string di mana beberapa tautan web sudah memiliki tautan href pada mereka. Dalam hal ini gagal mengacaukan tautan kerja yang ada.
AdamJones
17

Mengidentifikasi URL itu rumit karena sering dikelilingi oleh tanda baca dan karena pengguna sering tidak menggunakan bentuk lengkap dari URL. Banyak fungsi JavaScript ada untuk mengganti URL dengan hyperlink, tapi saya tidak dapat menemukan yang berfungsi serta urlizefilter dalam kerangka kerja web Django yang berbasis Python. Karena itu saya memindahkan urlizefungsi Django ke JavaScript:

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

Sebuah contoh:

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

Argumen kedua, jika benar, menyebabkan rel="nofollow"dimasukkan. Argumen ketiga, jika benar, lolos dari karakter yang memiliki arti khusus dalam HTML. Lihat file README .

Vebjorn Ljosa
sumber
Juga berfungsi dengan sumber html seperti: www.web.com <a href = "https: // github. Com"> url </ a> beberapa teks
Paulius Zaliaduonis
@ Paulius: jika Anda mengatur opsi django_compatibleke false, itu akan menangani kasus penggunaan yang sedikit lebih baik.
Vebjorn Ljosa
Django urlizetidak mendukung TLD dengan benar (setidaknya bukan port JS di GitHub). Perpustakaan yang menangani TLD dengan benar adalah Ben Alman JavaScript Linkify .
Dan Dascalescu
Dukungan untuk mendeteksi URL dengan domain tingkat atas tambahan bahkan ketika URL tidak dimulai dengan "http" atau "www" telah ditambahkan.
Vebjorn Ljosa
10

Saya membuat perubahan ke Roshambo String.linkify () ke emailAddressPattern untuk mengenali alamat 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
sumber
Kode di atas akan gagal banyak tes untuk kasus tepi. Saat mendeteksi URL, lebih baik mengandalkan perpustakaan khusus. Inilah sebabnya .
Dan Dascalescu
9

Saya mencari di Google untuk sesuatu yang lebih baru dan menemukan ini:

$('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/

Bekerja sangat baik untuk tautan normal.

merosot
sumber
Apa itu "Tautan normal" di sini? Lihatlah garpu demo Anda di sini: jsfiddle.net/hEgvc/27 Orang-orang akan membahasnya tanpa penutup dan akan membuatnya dengan cara yang mudah. URI bukanlah hal yang mudah sesuai RFC3986 dan jika Anda hanya ingin membahas "Tautan normal", saya sarankan untuk mengikuti regexp ini setidaknya: ^ (([^: /? #] +) +):)? (// ([ ^ /? #] *))? ([^? #] *) (\? ([^ #] *))? (# (. *))?
Ivan
2
Saya berarti apa pun dalam format http://example.com/folder/folder/folder/atau https://example.org/blahlainnya - hanya format URL tidak gila khas Anda yang akan cocok dengan 95-99% kasus penggunaan di luar sana. Saya menggunakan ini untuk area administrasi internal, jadi saya tidak perlu sesuatu yang mewah untuk menangkap kasus tepi atau hashlinks.
merosot
5

Solusi ini berfungsi seperti yang lain, dan pada kenyataannya menggunakan regex yang sama seperti salah satu dari mereka, namun sebagai ganti mengembalikan HTML String ini akan mengembalikan sebuah fragmen dokumen yang mengandung elemen A dan semua node teks yang berlaku.

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

Ada beberapa peringatan, yaitu dengan IE yang lebih lama dan dukungan textContent.

di sini adalah demo.

rlemon
sumber
2
@ DanDascalescu Alih-alih selimut downvoting banyak mungkin memberikan kasus tepi Anda.
rlemon
Apakah saya perlu? Lihatlah Komponen regexp untuk URL . Tetapi jika Anda bersikeras, lari melawan test suite link Ben Alman . Saya memang mulai berkontribusi gagal tes, misalnya untuk urlize , tetapi segera menyadari bahwa itu layak dilakukan hanya untuk upaya perpustakaan yang serius. Dengan segala hormat, jawaban di atas adalah jawaban StackOverflow, bukan pustaka bersumber terbuka yang mencoba mem-parsing URL dengan benar.
Dan Dascalescu
2
jadi ada kasus tepi. hebat. jawaban-jawaban ini mungkin masih bermanfaat bagi orang lain dan menyelimuti mereka tampaknya terlalu banyak. Jawaban lain yang telah Anda komentari dan tampaknya tidak digunakan memang berisi informasi yang berguna (dan juga jawaban Anda). tidak semua orang akan menentang kasus tersebut, dan tidak semua orang ingin menggunakan perpustakaan.
rlemon
Persis. Mereka yang tidak memahami batasan regexps adalah mereka yang akan dengan senang hati membaca regexp pertama dari jawaban yang paling banyak dipilih dan menjalankannya. Mereka adalah orang-orang yang harus menggunakan perpustakaan paling banyak.
Dan Dascalescu
1
Namun, bagaimana justifikasi untuk menurunkan suara setiap jawaban dengan regexp yang tidak Anda sukai?
rlemon
4

Jika Anda perlu menunjukkan tautan yang lebih pendek (hanya domain), tetapi dengan URL panjang yang sama, Anda dapat mencoba modifikasi saya dari versi kode Sam Hasler yang diposting di atas

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

Berikut adalah beberapa string yang diuji:

  1. Temukan saya di www.google.com
  2. www
  3. Temukan saya di www. http://www.com
  4. Ikuti saya di: http://www.nishantwork.wordpress.com
  5. http://www.nishantwork.wordpress.com
  6. Ikuti saya di: http://www.nishantwork.wordpress.com
  7. https://stackoverflow.com/users/430803/nishant

Catatan: Jika Anda tidak ingin lulus wwwsebagai valid, gunakan saja di bawah ini reg ex: /(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig

Nishant Kumar
sumber
Kode di atas akan gagal banyak tes untuk kasus tepi. Saat mendeteksi URL, SELALU lebih baik mengandalkan perpustakaan khusus. Inilah sebabnya .
Dan Dascalescu
3

Peringatan tentang kompleksitas URI harus dicatat, tetapi jawaban sederhana untuk pertanyaan Anda adalah:
Untuk mengganti setiap kecocokan Anda perlu menambahkan /gbendera ke akhir RegEx:
/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi

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

contoh sederhana

Zuhair Taha
sumber
2

Tetap sederhana! Katakan apa yang tidak bisa Anda miliki, daripada apa yang bisa Anda miliki :)

Seperti disebutkan di atas, URL bisa sangat kompleks, terutama setelah '?', Dan tidak semuanya dimulai dengan 'www.' misalnyamaps.bing.com/something?key=!"£$%^*()&lat=65&lon&lon=20

Jadi, daripada memiliki regex kompleks yang tidak akan memenuhi semua kasus tepi, dan akan sulit untuk mempertahankan, bagaimana dengan yang jauh lebih sederhana ini, yang bekerja dengan baik untuk saya dalam praktik.

Pertandingan

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

www. (anything but a space)+

Di mana 'apa pun' berada [^'"<>\s] ... pada dasarnya pertandingan serakah, membawa Anda bertemu spasi, kutipan, braket sudut, atau akhir baris

Juga:

Ingatlah untuk memeriksa bahwa itu belum dalam format URL, misalnya teks berisi href="..." atausrc="..."

Tambahkan ref = nofollow (jika sesuai)

Solusi ini tidak sebagus perpustakaan yang disebutkan di atas, tetapi jauh lebih sederhana, dan bekerja dengan baik dalam praktiknya.

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

Deteksi URL yang benar dengan dukungan domain internasional & karakter astral bukanlah hal sepele. linkify-itperpustakaan membangun regex dari banyak kondisi , dan ukuran akhir sekitar 6 kilobyte :). Ini lebih akurat daripada semua lib, saat ini dirujuk dalam jawaban yang diterima.

Lihat demo linkify-it untuk memeriksa semua kasus tepi langsung dan menguji yang Anda miliki .

Jika Anda perlu menautkan sumber HTML, Anda harus menguraikannya terlebih dahulu, dan mengulangi setiap token teks secara terpisah.

Vitaly
sumber
1

Saya telah menulis pustaka JavaScript yang lain, mungkin lebih baik bagi Anda karena sangat peka dengan kemungkinan kesalahan seminimal mungkin, cepat dan kecil. Saya saat ini secara aktif memeliharanya jadi tolong lakukan pengujian di halaman demo dan lihat bagaimana itu akan bekerja untuk Anda.

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

Alex C.
sumber
Perpustakaan yang luar biasa. Terima kasih banyak!
Serdar Değirmenci
0

Saya harus melakukan yang sebaliknya, dan membuat tautan html menjadi hanya URL, tapi saya memodifikasi regex Anda dan itu berfungsi seperti pesona, terima kasih :)

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

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

sumber
Saya tidak melihat titik regex Anda. Ini cocok dengan segalanya menggantikan segalanya dengan segalanya. Akibatnya, kode Anda tidak melakukan apa pun.
Chad Grant,
8
Saya kira saya harus menunggu untuk berkomentar agar orang selesai mengedit. Maaf.
Chad Grant,
0

Deteksi email dalam jawaban Travitron di atas tidak berfungsi untuk saya, jadi saya memperpanjang / menggantinya dengan yang berikut (kode 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);

Ini memungkinkan alamat email seperti " [email protected] ".

Uwe Keim
sumber
Kode di atas akan gagal banyak tes untuk kasus tepi. Saat mendeteksi URL, SELALU lebih baik mengandalkan perpustakaan khusus. Inilah sebabnya .
Dan Dascalescu
Terima kasih, @DanDascalescu Biasanya, selalu lebih baik untuk menggeneralisasi secara berlebihan.
Uwe Keim
0

Setelah input dari beberapa sumber, sekarang saya sudah solusi yang bekerja dengan baik. Itu ada hubungannya dengan menulis kode pengganti Anda sendiri.

Jawaban .

Biola .

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
sumber
2
Kode di atas (dan kebanyakan ekspresi reguler pada umumnya) akan gagal banyak tes untuk kasus tepi. Saat mendeteksi URL, lebih baik mengandalkan perpustakaan khusus. Inilah sebabnya .
Dan Dascalescu
Dan, apakah ada perpustakaan seperti itu? Meskipun dalam hal ini kita masih akan mencocokkan regex di atas sehingga kode tidak pernah dapat menghasilkan sampah ketika sesuatu seperti sampah (bahkan jika perpustakaan lain mengesahkan sampah sebagai URL / URI yang valid) digunakan sebagai input.
Mike Mestnik
0

Inilah solusi saya:

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

Coba fungsi di bawah ini:

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

Coba Solusi Di Bawah Ini

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
sumber