주어진 텍스트 내에서 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 을 구문 분석 할 때 매우 다양한 경우가 있습니다 .
내가 검토 한 톤 의 라이브러리 , 일부 단점에도 불구하고 사용하는 몇 가지 가치가있다 :
- Soapbox의 linkify 는 몇 가지 심각한 노력을 기울 였으며 2015 년 6 월 주요 리 팩터 가 jQuery 의존성을 제거했습니다 . 여전히 IDN에 문제 가 있습니다 .
- AnchorMe 는 더 빠르고 희박 하다고 주장 하는 새로운 이민자입니다 . 일부 IDN 문제 도 있습니다.
- Autolinker.js 는 기능을 매우 구체적으로 나열합니다 (예 : “HTML 입력을 올바르게 처리합니다. 유틸리티는
href
앵커 () 태그 안의 속성을 변경하지 않습니다 “ ). 데모를 사용할 수있게 되면 몇 가지 테스트를하겠습니다 .
이 작업을 위해 신속하게 실격 된 라이브러리 :
- Django의 urlize 는 특정 TLD를 올바르게 처리하지 못했습니다 ( 유효한 TLD 의 공식 목록이 있습니다. 데모 없음) .
- autolink-js 는 http : //없이 “www.google.com”을 감지하지 않으므로 일반 텍스트에서 발견 된 “캐주얼 URL”(체계 / 프로토콜없이)을 자동 링크하는 데 적합하지 않습니다.
- Ben Alman의 linkify 는 2009 년 이후로 유지되지 않았습니다.
정규식을 고집하면 Component 의 URL 정규 표현식 이 가장 포괄적 이지만, 존재하지 않는 2 문자 TLD를 살펴보면 잘못 감지합니다.
답변
URL을 링크로 바꾸기 (일반적인 문제에 대한 답변)
질문의 정규 표현식은 많은 경우를 놓칩니다. URL을 감지 할 때는 항상 국제 도메인 이름,와 같은 새로운 TLD .museum
, 괄호 및 URL 내부 및 끝에있는 구두점 및 기타 여러 가지 경우 를 처리하는 특수 라이브러리를 사용하는 것이 좋습니다 . 다른 문제에 대한 설명은 Jeff Atwood의 블로그 게시물 URL 관련 문제를 참조하십시오.
URL 매칭 라이브러리의 가장 요약 에 댄 Dascalescu의 대답
(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 함수가 존재하지만 urlize
Python 기반 웹 프레임 워크 Django에서 필터 뿐만 아니라 작동하는 함수도 찾을 수 없습니다 . 따라서 Django의 urlize
기능을 JavaScript 로 이식했습니다 .
예를 들면 :
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. <grin>"
두 번째 인수가 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>');
};
}