Last active
August 21, 2020 13:14
-
-
Save knoajp/a27015fc93b286a56d451da4c9bb8101 to your computer and use it in GitHub Desktop.
テキストのリンク化。高速かつ誤判定のない気持ちのよい動作を目指しています。
This file contains 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 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> | |
test.mail@mail.example.com | |
test@example.com | |
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://user@www.example.com/ | |
http://user:password@www.example.com/ | |
http://user:password@192.168.0.1/index.php?q=keywords#hash | |
http://localhost:80/ | |
in English: | |
My mail address is test@example.com. | |
My mail address is "test@example.com". | |
My mail address is test.mail@mail.example.com. | |
My mail address is "test.mail@mail.example.com". | |
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: | |
わたしのメールアドレスは test@example.com です。 | |
わたしのメールアドレスはtest@example.comです。 | |
わたしのメールアドレスは「test@example.com」です。 | |
わたしのウェブサイトは 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:test@example.com">test@example.com</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