[javascript] 일반 URL을 링크로 바꾸는 방법?

주어진 텍스트 내에서 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>");
}



답변

첫째, URL을 구문 분석하기 위해 자신의 정규 표현식을 굴리는 것은 끔찍한 아이디어 입니다. RFC 에 따르면 누군가가 라이브러리를 작성, 디버깅 및 테스트 했을 때 발생하는 일반적인 문제라고 생각해야합니다 . URI는 복잡 – 아웃 확인 Node.js를에서 URL 파싱 코드 와의 위키 백과 페이지 URI 체계를 .

국제 도메인 이름 , 실제 ( .museum) vs 존재하지 않는 ( .etc) TLD, 괄호를 포함한 이상한 구두점 , URL 끝에 구두점, IPV6 호스트 이름 등 URL 을 구문 분석 할 때 매우 다양한 경우가 있습니다 .

내가 검토 한 라이브러리 , 일부 단점에도 불구하고 사용하는 몇 가지 가치가있다 :

이 작업을 위해 신속하게 실격 된 라이브러리 :

정규식을 고집하면 ComponentURL 정규 표현식 이 가장 포괄적 이지만, 존재하지 않는 2 문자 TLD를 살펴보면 잘못 감지합니다.


답변

URL을 링크로 바꾸기 (일반적인 문제에 대한 답변)

질문의 정규 표현식은 많은 경우를 놓칩니다. URL을 감지 할 때는 항상 국제 도메인 이름,와 같은 새로운 TLD .museum, 괄호 및 URL 내부 및 끝에있는 구두점 및 기타 여러 가지 경우 를 처리하는 특수 라이브러리를 사용하는 것이 좋습니다 . 다른 문제에 대한 설명은 Jeff Atwood의 블로그 게시물 URL 관련 문제를 참조하십시오.

URL 매칭 라이브러리의 가장 요약댄 Dascalescu의 대답+100
(2014 2월 현재)


“정규식으로 두 개 이상의 일치 항목을 교체하십시오”(특정 문제에 대한 답변)

전역 표현식을 활성화하려면 정규 표현식 끝에 “g”를 추가하십시오.

/ig;

그러나 정규 표현식이 첫 번째 일치 항목 만 바꾸는 문제의 문제 만 수정합니다. 해당 코드를 사용하지 마십시오.


답변

Travis의 코드를 약간 수정했습니다 (불필요한 재 선언을 피하기 위해-그러나 그것은 내 필요에 따라 잘 작동합니다!) :

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


답변

Linkify()위의 Travis 코드 를 일부 최적화했습니다 . 또한 하위 도메인 유형 형식의 이메일 주소가 일치하지 않는 버그를 수정했습니다 (예 : 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>');
    };
}


답변

감사합니다. 매우 도움이되었습니다. 또한 URL처럼 보이는 것들을 연결하는 무언가를 원했습니다. 기본 요구 사항은 http : // 프로토콜 접두사가없는 경우에도 www.yahoo.com과 같은 것을 연결하는 것입니다. 기본적으로 “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.whatever.com 만 //로 대체합니다. 첫 번째 교체에서 URL이 이미 연결된 경우 이중 연결을 피하기위한 것입니다. 또한 www.whatever.com이 문자열의 시작 부분에있을 수 있습니다. 이는 정규 표현식의 해당 부분에서 첫 번째 “조건”입니다.

Jesse P가 위에서 설명한 것처럼 jQuery 플러그인으로 통합 될 수는 있지만 기존 DOM 요소에 대해 작동하지 않는 일반 함수를 원했습니다. 텍스트를 가져 와서 DOM에 추가하기 때문입니다. 텍스트를 추가하기 전에 “연결”되기를 원하므로이 함수를 통해 텍스트를 전달합니다. 잘 작동합니다.


답변

URL은 구두점으로 둘러싸여 있고 사용자가 URL의 전체 형식을 자주 사용하지 않기 때문에 URL을 식별하기가 까다 롭습니다. URL을 하이퍼 링크로 대체하기위한 많은 JavaScript 함수가 존재하지만 urlizePython 기반 웹 프레임 워크 Django에서 필터 뿐만 아니라 작동하는 함수도 찾을 수 없습니다 . 따라서 Django의 urlize기능을 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;"

두 번째 인수가 true이면 rel="nofollow"삽입됩니다. 세 번째 인수 (true 인 경우)는 HTML에서 특별한 의미가있는 문자를 이스케이프합니다. README 파일을 참조하십시오 .


답변

aaa.bbb. @ ccc.ddd 주소를 인식하기 위해 Roshambo String.linkify ()를 emailAddressPattern으로 변경했습니다.

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