Як замінити прості URL-адреси посиланнями?


454

Я використовую функцію нижче, щоб співставити URL-адреси всередині певного тексту та замінити їх на HTML-посилання. Регулярний вираз працює чудово, але наразі я замінюю лише перший матч.

Як я можу замінити всю URL-адресу? Я думаю, я повинен використовувати команду exec , але я не дуже зрозумів, як це зробити.

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

Відповіді:


351

По-перше, жахлива ідея прокатки власного регулярного выраження для розбору URL-адрес . Ви повинні уявити, що це досить поширена проблема, що хтось написав, налагодив і перевірив бібліотеку для неї, згідно з даними RFC . URI є складними - ознайомтеся з кодом для розбору URL-адрес у Node.js та на сторінці Вікіпедії на схемах URI .

Існує безліч випадкових випадків, коли мова йде про розбір URL-адрес: міжнародні доменні імена , фактичні ( .museum) проти неіснуючих ( .etc) TLD, дивні пунктуації, включаючи дужки , пунктуацію в кінці URL-адреси, імена хостів IPV6 тощо.

Я подивився на тонну в бібліотеках , і є кілька варто використовувати , незважаючи на деякі мінуси:

Бібліотеки, які я швидко дискваліфікував для цього завдання:

Якщо ви наполягаєте на регулярному виразі, найбільш вичерпним є URL-регепс від Component , хоча він помилково виявить деякі неіснуючі двобуквенні TLD, дивлячись на нього.


3
Шкода, що URL regexp from Componentне коментують, корисне було б якесь пояснення того, що це робиться. Autolinker.jsкоментується дуже добре і має тести. urlize.jsБібліотека пов'язана в відповіді Vebjørn Ljosa в теж виглядає і функціональної добре підтримуються, хоча він не має тестів.
Сем Хаслер,

1
Regex101.com автоматично "пояснює" regexp, але удачі з цим :) Я також швидко знайшов випадок помилки з недійсним TLD (те саме посилання).
Дан Даскалеску

1
@SamHasler: Autolinker потребує вдосконалення в області TLD та IDN. Додано кілька тестів .
Дан Даскалеску

2
Цікаво, що ніхто не згадував зусилля Джона Грубера у підтримці схеми зворотного вираження URL-адрес . Це не єдине / ідеальне рішення проблеми, але, у будь-якому випадку, варто вивчити, чи ви переймаєте власне рішення. Просто хотів додати це як посилання.
oelna

2
@DanDascalescu Погляньте на цей markdown-it.github.io/linkify-it . Ця бібліотека орієнтована саме на одне завдання - виявлення шаблонів посилань у тексті. Але я сподіваюся, це робить це добре. Наприклад, він має правильну підтримку unicode, включаючи астральних символів. І він підтримує міжнародні TLD.
Віталій

285

Заміна URL-адрес посиланнями (відповідь на загальну проблему)

Регулярний вираз у питанні пропускає безліч крайніх випадків. Виявляючи URL-адреси, завжди краще використовувати спеціалізовану бібліотеку, яка обробляє міжнародні доменні імена, нові TLD, наприклад .museum, дужки та інші пунктуаційні знаки в межах та в кінці URL-адреси, та багато інших кращих справ. Дивіться публікацію в блозі Джеффа Етвуда Проблема з URL-адресами для пояснення деяких інших проблем.

Найкраще резюме узгоджувальних бібліотек URL в Відповідь Dan Dăscălescu в+100
(станом на лютий 2014 роки)


"Зробити регулярний вираз замінити більше однієї відповідності" (Відповідь на конкретну проблему)

Додайте "g" до кінця регулярного виразу, щоб увімкнути глобальну відповідність:

/ig;

Але це лише вирішує проблему в питанні, коли регулярний вираз заміняв лише першу відповідність. Не використовуйте цей код.


150

Я вніс кілька невеликих змін до коду Тревіса (просто щоб уникнути зайвих передекларацій - але він чудово працює для моїх потреб, така приємна робота!):

function linkify(inputText) {
    var replacedText, replacePattern1, replacePattern2, replacePattern3;

    //URLs starting with http://, https://, or ftp://
    replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
    replacedText = inputText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>');

    //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
    replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
    replacedText = replacedText.replace(replacePattern2, '$1<a href="http://$2" target="_blank">$2</a>');

    //Change email addresses to mailto:: links.
    replacePattern3 = /(([a-zA-Z0-9\-\_\.])+@[a-zA-Z\_]+?(\.[a-zA-Z]{2,6})+)/gim;
    replacedText = replacedText.replace(replacePattern3, '<a href="mailto:$1">$1</a>');

    return replacedText;
}

1
як редагувати цей код, щоб не завдати шкоди вбудованим об'єктам та рамкам .. (вбудовані в YouTube об’єкти та
рамки

5
У коді є помилка, яка відповідає адресам електронної пошти. [a-zA-Z]{2,6}Ви повинні прочитати щось уздовж рядка (?:[a-zA-Z]{2,6})+, щоб відповідати складнішим доменним іменам, тобто email@example.co.uk.
Рошамбо

1
Я зіткнувся з деякими проблемами; спочатку просто http: // або http: // www (без пробілу www навіть ТАК аналізує це неправильно, мабуть) створить посилання. І посилання з http: // www. домен. com (без пробілів) створить одне порожнє посилання, а потім одне із доданим тегом для закриття тега в полі href.
Альфред

1
Що з URL-адресами без http://або www? Чи працюватиме це для таких URL-адрес?
Натан

2
Я спробував відредагувати оригінальну публікацію, щоб виправити проблему з поштовим повідомленням, але мені потрібно додати щонайменше 6 символів, щоб внести зміни. Але якщо ви зміните цей рядок: за replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;допомогою цього replacePattern3 = /(\w+@[a-zA-Z_]+?(\.[a-zA-Z]{2,6})+)/gim;виправляєте проблему mailto :)
yourdeveloperfriend

70

Linkify()Вище провели оптимізацію коду Травіса . Я також виправив помилку, коли адреси електронної пошти з форматами піддоменного типу не відповідали (наприклад, example@domain.co.uk).

Крім того, я змінив реалізацію на прототип Stringкласу, щоб елементи можна було зіставити так:

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

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

У будь-якому випадку, ось сценарій:

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

На мій погляд, найкраще, оскільки функції прототипу роблять речі набагато чистішими :)
MRVDOG

здається, він не працює з такими адресами електронної пошти: info@some-thing.com some.thing@example.com тощо.
Marco Gagliardi

@MarcoGagliardi Хороший улов. Виправлено.
Рошамбо

1
Це не працює для рядка "git clone aaaa@bitbucket.org/ooo/bbb-cc-dd.git ". Він розірвав рядок на шматки і створив кілька якорів на кшталт цього "git clone <a href="https://<a href="mailto:aaaa@bitbucket.org"> aaaa@bitbucket.org </a> / ooo / bbb-cc-dd.git "> https: // <a href="mailto:aaaa@bitbucket.org"> aaaa@bitbucket.org </a> /ooo/bbb-cc-dd.git </a> "
Джебін

1
Це не працює +в іменах користувачів електронної пошти, таких як foo+bar@domain.com. Я виправив це за допомогою шаблону електронної пошти /[\w.+]+@[a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim(зверніть увагу на +перші дужки), але я не знаю, чи це порушує щось інше.
dchacke

24

Дякую, це було дуже корисно. Я також хотів щось, що пов'язувало б речі, схожі на URL - як основна вимога, воно пов'язувало б щось на зразок www.yahoo.com, навіть якщо префіксу протоколу http: // немає. Так в основному, якщо "www." присутній, він зв’яже це і припустить, що це http: //. Я також хотів, щоб електронні листи перетворилися на mailto: посилання. ПРИКЛАД: www.yahoo.com буде перетворений на www.yahoo.com

Ось код, який я закінчив (поєднання коду на цій сторінці та інших речей, які я знайшов в Інтернеті, та інших речей, які я робив самостійно):

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
}

У другій заміні частина (^ | [^ /]) замінює www.wever.com лише тоді, коли вона не є префіксом // - щоб уникнути подвійного посилання, якщо URL-адреса вже була пов’язана в першій заміні. Крім того, можливо, що www.wwhat.com може бути на початку рядка, що є першою умовою "або" у цій частині регулярного виразів.

Це може бути інтегровано як плагін jQuery, як показано вище Jesse P - але я спеціально хотів регулярної функції, яка не діяла на існуючий елемент DOM, тому що я беру текст, який я маю, а потім додаю його до DOM, і Я хочу, щоб текст був "зв'язаний" перед тим, як додати його, тому я передаю текст через цю функцію. Чудово працює.


1
Існує проблема з другою схемою, яка сама по собі відповідає "www.domain.com". Проблема існує, коли в URL-адресі є якийсь посилання, наприклад: & 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 - у цьому випадку посилання автоматично зв’язується знову. Швидке виправлення полягає в тому, щоб додати символ "f" після списку заперечень, який містить "/". Тож вираз: замінитиPattern2 = /(^|
evidence

Наведений вище код провалить безліч тестів для кращих випадків. Виявляючи URL-адреси, краще покластися на спеціалізовану бібліотеку. Ось чому .
Дан Даскалеску

2
Я просто запустив його на рядок, де в деяких веб-посиланнях уже є посилання на href. У цьому випадку вона не зіпсує існуючі робочі ланки.
AdamJones

17

Ідентифікувати URL-адреси складно, оскільки вони часто оточені пунктуаційними знаками і тому, що користувачі часто не використовують повну форму URL-адреси. Існує багато функцій JavaScript для заміни URL-адрес гіперпосиланнями, але мені не вдалося знайти таку, яка працює, а також urlizeфільтр у веб-рамках Django на основі Python. Тому я переніс urlizeфункцію Django в JavaScript:

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

Приклад:

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

Другий аргумент, якщо істинний, викликає rel="nofollow"вставлення. Третій аргумент, якщо це правда, уникає символів, які мають особливе значення в HTML. Дивіться файл README .


Також працює з html-джерелом на зразок: www.web.com <a href = "https: // github. Com"> url </a> якийсь текст
Paulius Zaliaduonis

@Paulius: якщо встановити параметр " django_compatiblefalse", він буде обробляти цю справу трохи краще.
Вебйорн Льоса

Django urlizeне підтримує TLD належним чином (принаймні, не JS-порт на GitHub). Бібліотека, яка належним чином обробляє TLD, є JavaScript Linkify Бен Альмана .
Дан Даскалеску

Підтримка виявлення URL-адрес з додатковими доменами верхнього рівня, навіть якщо URL-адреса не починається з "http" або "www" додана.
Вебйорн Льоса

10

Я змінив Roshambo String.linkify () на emailAddressPattern, щоб розпізнати адреси 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>');
    };
}

Наведений вище код провалить безліч тестів для кращих випадків. Виявляючи URL-адреси, краще покластися на спеціалізовану бібліотеку. Ось чому .
Дан Даскалеску

9

Я шукав у Google щось нове і наткнувся на цей:

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

демо: http://jsfiddle.net/kachibito/hEgvc/1/

Працює дуже добре для нормальних посилань.


Що тут "Звичайні посилання"? Подивіться на вилку демо-версії тут: jsfiddle.net/hEgvc/27 Люди охоплюватимуть непокриті та роблять це легким способом. URI - це непроста річ відповідно до RFC3986, і якщо ви хочете охопити лише "Звичайні посилання", я пропоную принаймні дотримуватися цього regexp: ^ (([^: /? #] +):)? "// // ([ ^ /? #] *))? ([^? #] *) (\? ([^ #] *))? (# (. *))?
Іван

2
Я мав на увазі що-небудь у форматі http://example.com/folder/folder/folder/чи https://example.org/blahіншому - просто ваш типовий не божевільний формат URL, який відповідає 95-99% випадків використання. Я використовую це для внутрішньої адміністративної сфери, тому мені не потрібно нічого фантазії, щоб зафіксувати кращі регістри чи хешлінки.
вироджений


5

Це рішення працює, як і багато інших, і фактично використовує той же регулярний вираз, що і один з них, однак замість повернення рядка HTML це поверне фрагмент документа, що містить елемент A та будь-які застосовні текстові вузли.

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

Існують деякі застереження, а саме зі старшою підтримкою IE та textContent.

ось демонстрація.


2
@DanDascalescu Замість ковдри забороняючи лот, можливо, надайте ваші згадані крайові випадки.
rlemon

Чи потрібно мені? Подивіться на регулярне вираження компонентів для URL-адрес . Але якщо ви наполягаєте, біжіть проти тестового набору Бен Альмана . Я почав надсилати пробні тести, наприклад, для urlize , але незабаром зрозумів, що це варто робити лише для серйозних зусиль бібліотеки. З усією повагою, вищевказаний - відповідь StackOverflow, а не відкрита бібліотека, що намагається правильно розібрати URL-адреси.
Дан Даскалеску

2
тому є крайові випадки. чудовий. ці відповіді все-таки можуть бути корисними для інших, і ковдра, зволікаючи їх, здається непосильним. Інші відповіді, які ви прокоментували, і, здавалося б, заперечували , містять корисну інформацію (а також вашу відповідь). не кожен зіткнеться із зазначеними справами, і не кожен захоче користуватися бібліотекою.
румон

Саме так. Ті, хто не розуміє обмежень регулярних виразів, - це ті, хто із задоволенням проскакує перший регепс з найбільш схваленої відповіді і побіжить з ним. Це люди, яким найбільше слід користуватися бібліотеками.
Дан Даскалеску

1
Але як це обгрунтування, щоб уникнути голосування за кожну відповідь нерегульованими рішеннями regexp?
рулемон

4

Якщо вам потрібно показати коротше посилання (лише домен), але з такою ж довгою URL-адресою, ви можете спробувати мою модифікацію версії коду Сема Хаслера, розміщену вище

function replaceURLWithHTMLLinks(text) {
    var exp = /(\b(https?|ftp|file):\/\/([-A-Z0-9+&@#%?=~_|!:,.;]*)([-A-Z0-9+&@#%?\/=~_|!:,.;]*)[-A-Z0-9+&@#\/%=~_|])/ig;
    return text.replace(exp, "<a href='$1' target='_blank'>$3</a>");
}

3

Рег. 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>");
}

Нижче наведено кілька тестованих рядків:

  1. Знайдіть мене на www.google.com
  2. www
  3. Знайдіть мене на www. http://www.com
  4. Слідкуйте за мною: http://www.nishantwork.wordpress.com
  5. http://www.nishantwork.wordpress.com
  6. Слідкуйте за мною: http://www.nishantwork.wordpress.com
  7. https://stackoverflow.com/users/430803/nishant

Примітка. Якщо ви не хочете перейти wwwяк дійсний, просто скористайтеся нижче reg ex: /(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig


Наведений вище код провалить безліч тестів для кращих випадків. Виявляючи URL-адреси, ЗАВЖДИ краще покластися на спеціалізовану бібліотеку. Ось чому .
Дан Даскалеску

3

Попередження про складність URI слід зазначити, але проста відповідь на ваше запитання:
Щоб замінити кожну відповідність, потрібно додати /gпрапор до кінця RegEx:
/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi


3
/**
 * Convert URLs in a string to anchor buttons
 * @param {!string} string
 * @returns {!string}
 */

function URLify(string){
  var urls = string.match(/(((ftp|https?):\/\/)[\-\w@:%_\+.~#?,&\/\/=]+)/g);
  if (urls) {
    urls.forEach(function (url) {
      string = string.replace(url, '<a target="_blank" href="' + url + '">' + url + "</a>");
    });
  }
  return string.replace("(", "<br/>(");
}

простий приклад


2

Не ускладнювати! Скажіть, що ви не можете мати, а не те, що ви можете мати :)

Як було сказано вище, URL-адреси можуть бути досить складними, особливо після "?", І не всі вони починаються з "www". напрmaps.bing.com/something?key=!"£$%^*()&lat=65&lon&lon=20

Отже, а не мати складний регулярний вираз, який не відповідає всім крайовим випадкам, і його важко буде підтримувати, як щодо цього набагато простішого, який добре працює для мене.

Матч

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

www. (anything but a space)+

Де "що-небудь" - [^'"<>\s] це в основному жадібна відповідність, що веде до вас пробіл, цитату, кутову дужку або кінець рядка

Також:

Не забудьте перевірити, чи він вже не у форматі URL, наприклад, текст містить href="..."абоsrc="..."

Додати ref = nofollow (якщо потрібно)

Це рішення не настільки «добре», як вищезгадані бібліотеки, але набагато простіше і добре працює на практиці.

if html.match( /(href)|(src)/i )) {
    return html; // text already has a hyper link in it
    }

html = html.replace( 
            /\b(https?:\/\/[^\s\(\)\'\"\<\>]+)/ig, 
            "<a ref='nofollow' href='$1'>$1</a>" 
            );

html = html.replace( 
            /\s(www\.[^\s\(\)\'\"\<\>]+)/ig, 
            "<a ref='nofollow' href='http://$1'>$1</a>" 
            );

html = html.replace( 
             /^(www\.[^\s\(\)\'\"\<\>]+)/ig, 
            "<a ref='nofollow' href='http://$1'>$1</a>" 
            );

return html;

2

Правильне виявлення URL-адрес з міжнародними доменами та підтримкою астральних символів - це не дрібниця. linkify-itБібліотека будує регулярні вирази з багатьох умов , а кінцевий розмір становить близько 6 кілобайт :). Це точніше за всі лібси, на які в даний час посилається прийнята відповідь.

Перегляньте демонстраційну версію linkify-it, щоб перевірити всі випадки реального життя та перевірити свої.

Якщо вам потрібно зв’язати джерело HTML, слід спершу проаналізувати його та повторити кожен маркер тексту окремо.


1

Я написав ще одну бібліотеку JavaScript, можливо, це буде для вас краще, оскільки вона дуже чутлива з найменшими можливими помилковими позитивами, швидкими та малими розмірами. В даний час я активно підтримую його, тому, будь ласка, протестуйте його на демонстраційній сторінці і подивіться, як він буде працювати для вас.

посилання: https://github.com/alexcorvi/anchorme.js


Дивовижна бібліотека. Дуже дякую!
Serdar Değirmenci

0

Мені довелося зробити навпаки, і ввести HTML-посилання просто в URL-адресу, але я змінив ваш регулярний вираз, і він працює як шарм, дякую :)

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

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

Я не бачу сенсу у твоєму регулярному вираженні. Він відповідає усьому, замінюючи все на все. Насправді ваш код нічого не робить.
Чад Грант

8
Напевно, мені варто почекати коментарів, щоб люди могли закінчити редагування. вибачте.
Чад Грант

0

Виявлення електронної пошти у відповіді Травітрона вище для мене не працювало, тому я продовжив / замінив її наступним (код 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);

Це дозволяє отримувати адреси електронної пошти типу " firstname.secondname@one.two.three.co.uk ".


Наведений вище код провалить безліч тестів для кращих випадків. Виявляючи URL-адреси, ЗАВЖДИ краще покластися на спеціалізовану бібліотеку. Ось чому .
Дан Даскалеску

Дякую, @DanDascalescu Зазвичай, завжди краще надмірно узагальнити.
Уве Кеїм

0

Після введення інформації з декількох джерел я тепер вирішив, що добре працює. Це було пов'язано з написанням власного коду заміни.

Відповідь .

Скрипка .

function replaceURLWithHTMLLinks(text) {
    var re = /(\(.*?)?\b((?:https?|ftp|file):\/\/[-a-z0-9+&@#\/%?=~_()|!:,.;]*[-a-z0-9+&@#\/%=~_()|])/ig;
    return text.replace(re, function(match, lParens, url) {
        var rParens = '';
        lParens = lParens || '';

        // Try to strip the same number of right parens from url
        // as there are left parens.  Here, lParenCounter must be
        // a RegExp object.  You cannot use a literal
        //     while (/\(/g.exec(lParens)) { ... }
        // because an object is needed to store the lastIndex state.
        var lParenCounter = /\(/g;
        while (lParenCounter.exec(lParens)) {
            var m;
            // We want m[1] to be greedy, unless a period precedes the
            // right parenthesis.  These tests cannot be simplified as
            //     /(.*)(\.?\).*)/.exec(url)
            // because if (.*) is greedy then \.? never gets a chance.
            if (m = /(.*)(\.\).*)/.exec(url) ||
                    /(.*)(\).*)/.exec(url)) {
                url = m[1];
                rParens = m[2] + rParens;
            }
        }
        return lParens + "<a href='" + url + "'>" + url + "</a>" + rParens;
    });
}

2
Наведений вище код (і більшість регулярних виразів загалом) провалить безліч тестів для кращих випадків. Виявляючи URL-адреси, краще покластися на спеціалізовану бібліотеку. Ось чому .
Дан Даскалеску

Ден, чи є така бібліотека? Хоча в цьому випадку ми все одно співпадаємо з вищевказаним регулярним виразом, щоб код ніколи не виводив сміття, коли щось на зразок сміття (навіть якщо інша бібліотека засвідчує сміття як дійсну URL-адресу / URI) використовується як вхід.
Майк Местник


0

Ось моє рішення:

var content = "Visit https://wwww.google.com or watch this video: https://www.youtube.com/watch?v=0T4DQYgsazo and news at http://www.bbc.com";
content = replaceUrlsWithLinks(content, "http://");
content = replaceUrlsWithLinks(content, "https://");

function replaceUrlsWithLinks(content, protocol) {
    var startPos = 0;
    var s = 0;

    while (s < content.length) {
        startPos = content.indexOf(protocol, s);

        if (startPos < 0)
            return content;

        let endPos = content.indexOf(" ", startPos + 1);

        if (endPos < 0)
            endPos = content.length;

        let url = content.substr(startPos, endPos - startPos);

        if (url.endsWith(".") || url.endsWith("?") || url.endsWith(",")) {
            url = url.substr(0, url.length - 1);
            endPos--;
        }

        if (ROOTNS.utils.stringsHelper.validUrl(url)) {
            let link = "<a href='" + url + "'>" + url + "</a>";
            content = content.substr(0, startPos) + link + content.substr(endPos);
            s = startPos + link.length;
        } else {
            s = endPos + 1;
        }
    }

    return content;
}

function validUrl(url) {
    try {
        new URL(url);
        return true;
    } catch (e) {
        return false;
    }
}

0

Спробуйте виконати наступну функцію:

function anchorify(text){
  var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
  var text1=text.replace(exp, "<a href='$1'>$1</a>");
  var exp2 =/(^|[^\/])(www\.[\S]+(\b|$))/gim;
  return text1.replace(exp2, '$1<a target="_blank" href="http://$2">$2</a>');
}

alert(anchorify("Hola amigo! https://www.sharda.ac.in/academics/"));


0

Спробуйте нижче рішення

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;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.