Skip to content

Instantly share code, notes, and snippets.

@knoajp
Last active August 21, 2020 13:14
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save knoajp/a27015fc93b286a56d451da4c9bb8101 to your computer and use it in GitHub Desktop.
Save knoajp/a27015fc93b286a56d451da4c9bb8101 to your computer and use it in GitHub Desktop.
テキストのリンク化。高速かつ誤判定のない気持ちのよい動作を目指しています。
(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);
})();
<!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