Last active
August 21, 2020 13:14
-
-
Save knoajp/a27015fc93b286a56d451da4c9bb8101 to your computer and use it in GitHub Desktop.
テキストのリンク化。高速かつ誤判定のない気持ちのよい動作を目指しています。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(){ | |
const linkify = function(node){ | |
split(node); | |
function split(n){ | |
if(['style', 'script', 'textarea', 'select', 'button', 'a'].includes(n.localName)) return; | |
if(n.nodeType === Node.TEXT_NODE){ | |
let pos = n.data.search(linkify.RE); | |
if(0 <= pos){ | |
let target = n.splitText(pos);/*pos直前までのnとpos以降のtargetに分割*/ | |
let rest = target.splitText(RegExp.lastMatch.length);/*targetと続くrestに分割*/ | |
/* この時点でn(処理済み),target(リンクテキスト),rest(次に処理)の3つに分割されている */ | |
let a = document.createElement('a'); | |
let match = target.data.match(linkify.RE); | |
switch(true){ | |
case(match[1] !== undefined): a.href = 'mailto:' + match[1]; break; | |
case(match[2] !== undefined): a.href = match[2]; break; | |
case(match[3] !== undefined): a.href = 'http://' + match[3]; break; | |
} | |
a.appendChild(target);/*textContent*/ | |
rest.parentNode.insertBefore(a, rest); | |
} | |
}else{ | |
for(let i = 0; n.childNodes[i]; i++) split(n.childNodes[i]);/*回しながらchildNodesは増えていく*/ | |
} | |
} | |
}; | |
linkify.RE = new RegExp([ | |
'(\\w[-\\w_.]+@\\w[-\\w_.]+\\w)',/*メールアドレス*/ | |
'(https?://(?:[-\\w_/~*%$@:;!?&=+#.,]+[-\\w_/~*%$@:;!?&=+#]|\\([^)]*\\))+)',/*通常のURL*/ | |
'((?:[\\w-]+\\.)+[-\\w_/~*%$@:;!?&=+#.,()]+[-\\w_/~*%$@:;!?&=+#])',/*http://の省略形*/ | |
].join('|')); | |
document.body.normalize(); | |
linkify(document.body); | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE HTML> | |
<html lang="ja"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Linkification test</title> | |
</head> | |
<body> | |
<pre> | |
[email protected] | |
[email protected] | |
http://www.subdomain.example.com/index.html?q=keywords#hash | |
http://www.example.com/index.html?q=keywords#hash | |
ttp://www.example.com/index.html?q=keywords#hash | |
www.example.com/index.html?q=keywords#hash | |
example.com/index.html?q=keywords#hash | |
http://example-example.com/ | |
http://example--example.com/ | |
http://www.example.com/abc | |
http://www.example.com/ | |
http://www.example.com | |
ttp://www.example.com | |
www.example.com | |
example.com/abc | |
example.com | |
123.example.com/abc | |
123.example.com/abc.html | |
123.example-test.com/abc.html | |
http://[email protected]/ | |
http://user:[email protected]/ | |
http://user:[email protected]/index.php?q=keywords#hash | |
http://localhost:80/ | |
in English: | |
My mail address is [email protected]. | |
My mail address is "[email protected]". | |
My mail address is [email protected]. | |
My mail address is "[email protected]". | |
My web site is http://example.com/. | |
My web site is "http://example.com/". | |
My web site is example.com. | |
Go to my web site(http://www.example.com/index.html?q=keywords#hash). | |
URL with parentheses https://en.wikipedia.org/wiki/Trump_(card_games). | |
in Japanese: | |
わたしのメールアドレスは [email protected] です。 | |
わたしのメールアドレスは[email protected]です。 | |
わたしのメールアドレスは「[email protected]」です。 | |
わたしのウェブサイトは http://example.com/ です。 | |
わたしのウェブサイトはhttp://example.com/です。 | |
わたしのウェブサイトは「http://example.com/」です。 | |
わたしのウェブサイト(http://www.example.com/index.html?q=keywords#hash)に行ってください。 | |
カッコ付きのウェブサイトhttps://en.wikipedia.org/wiki/Trump_(card_games)。 | |
エンコードされたURL https://ja.wikipedia.org/wiki/%E3%83%88%E3%83%A9%E3%83%B3%E3%83%97 | |
エンコードされていないURL https://ja.wikipedia.org/wiki/トランプ (対象外) | |
</pre> | |
<form> | |
<textarea rows="2" cols="80">http://www.example.com/index.html?q=keywords#hash</textarea> | |
<br> | |
<select> | |
<option>http://www.example.com/index.html?q=keywords#hash</option> | |
</select> | |
<br> | |
<button>http://www.example.com/index.html?q=keywords#hash</button> | |
</form> | |
<p>http://www.<strong style="color:red">example</strong>.com/index.html?q=keywords#hash (URLがDOM上で分割されている場合はあきらめる)</p> | |
<p><a href="http://www.example.com/index.html?q=keywords#hash">http://www.example.com/index.html?q=keywords#hash</a> (リンク済み)</p> | |
<p><a href="mailto:[email protected]">[email protected]</a> (リンク済み)</p> | |
<p>test@example.com (全角@は拾わない)</p> | |
<p>(以下に style と script 要素あり)</p> | |
<style> | |
span{background:url("http://www.example.com/example.png")} | |
</style> | |
<script> | |
function test(){ | |
alert('http://www.example.com/index.html?q=keywords#hash'); | |
} | |
</script> | |
<p><a href="javascript:void()" onClick="test()">alert(url) テスト</a></p> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment