일반 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 을 구문 분석 할 때 매우 다양한 경우가 있습니다 .
내가 검토 한 톤 의 라이브러리 , 일부 단점에도 불구하고 사용하는 몇 가지 가치가있다 :
- 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 regexp 가 가장 포괄적 이지만, 존재하지 않는 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>');
};
}
나는 구글에서 새로운 것을 찾아서 이것을 가로 질러 달렸다.
$('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/
일반 링크에 정말 효과적입니다.
가장 좋은 스크립트 : http://benalman.com/projects/javascript-linkify-process-lin/
이 솔루션은 다른 많은 솔루션과 동일하게 작동하며 실제로는 그 중 하나와 동일한 정규식을 사용하지만 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 지원과 같은 몇 가지주의 사항이 있습니다.
여기 데모가 있습니다.
더 짧은 링크 (도메인 만 해당)를 표시해야하지만 동일한 긴 URL을 사용하려면 위에 게시 된 Sam Hasler의 코드 버전을 수정 해보십시오
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>");
}
정규직 : /(\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>");
}
아래는 테스트 된 문자열입니다.
- www.google.com에서 나를 찾으십시오.
- www
- www에서 저를 찾으십시오. http://www.com
- 나를 따라와 : http://www.nishantwork.wordpress.com
- http://www.nishantwork.wordpress.com
- 나를 따라와 : http://www.nishantwork.wordpress.com
- https://stackoverflow.com/users/430803/nishant
참고 : www
유효한 것으로 전달하지 않으려면 reg ex 아래를 사용하십시오./(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig
URI의 복잡성에 대한 경고에 주목해야하지만 질문에 대한 간단한 대답은 다음과 같습니다.
모든 일치 항목을 바꾸려면 /g
RegEx 끝에 플래그를 추가해야합니다 .
/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi
간단하게 유지하십시오! 가질 수있는 것보다는 가질 수없는 것을 말하십시오. :)
위에서 언급했듯이 URL은 특히 '?'뒤에 매우 복잡 할 수 있으며 모든 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;
국제 도메인 및 아스트랄 문자 지원을 통한 올바른 URL 탐지는 사소한 것이 아닙니다. linkify-it
라이브러리는 많은 조건 에서 정규식을 빌드 하며 최종 크기는 약 6 킬로바이트입니다. 현재 허용되는 답변에서 참조되는 모든 라이브러리보다 정확합니다.
linkify-it 데모 를 참조 하여 모든 최신 사례를 확인하고 테스트하십시오.
HTML 소스를 연결해야하는 경우 먼저 HTML 소스를 구문 분석하고 각 텍스트 토큰을 개별적으로 반복해야합니다.
나는 또 다른 JavaScript 라이브러리를 작성했습니다. 가장 작은 크기의 오 탐지로 매우 민감하기 때문에 더 좋을 것입니다. 현재 적극적으로 유지 관리하고 있으므로 데모 페이지에서 테스트하여 어떻게 작동하는지 확인하십시오.
링크 : https://github.com/alexcorvi/anchorme.js
나는 반대로해야하고 URL에 HTML 링크를 만들어야했지만 정규 표현식을 수정하면 매력처럼 작동합니다. :)
var exp = /<a\s.*href=['"](\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_ |! :,.;] * [-A-Z0-9 + & @ # \ / % = ~ _ |]) [ ' "]. *>. * <\ / a> / ig; source = source.replace (exp, "$ 1");
위의 Travitron의 답변에서 전자 메일 감지가 작동하지 않아서 다음 (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 " 와 같은 이메일 주소를 허용합니다 .
여러 소스에서 입력 한 후 이제는 잘 작동하는 솔루션을 찾았습니다. 자체 교체 코드를 작성하는 것과 관련이 있습니다.
대답 .
바이올린 .
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;
});
}
텍스트의 URL을 HTML 링크로 바꾸고 href / pre 태그 내의 URL을 무시하십시오. https://github.com/JimLiu/auto-link
내 해결책은 다음과 같습니다.
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;
}
}
아래 기능을 사용해보십시오 :
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/"));
아래 솔루션을 사용해보십시오
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;
}
/**
* 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/>(");
}
참고 URL : https://stackoverflow.com/questions/37684/how-to-replace-plain-urls-with-links
'Programming' 카테고리의 다른 글
명부 (0) | 2020.02.18 |
---|---|
병합 충돌을 일으키는 git stash pop 실행 취소 (0) | 2020.02.18 |
어떤 버전의 jQuery가로드되었는지 확인하는 방법은 무엇입니까? (0) | 2020.02.18 |
OSX에서 JAVA_HOME을 무엇으로 설정해야합니까? (0) | 2020.02.18 |
URL 쿼리 매개 변수가 포함 된 HTTP POST-좋은 아이디어입니까? (0) | 2020.02.18 |