文章内のURLを自動リンク化する方法は多く記事にされていたのですが、加えてHTMLのaタグも使用可能にするというのに苦労したので記事にしました。
まず、「1.文章内のURLを半角スペースで自動リンク化」する方法をご紹介します。
その次に「2.HTMLのaタグも一緒に使用」する方法をご紹介します。
DBに保存されている文字列を表示するのか、
今HTMLで表示されているものを自動リンクに組み替えて再表示するのかで、結果が異なるかもしれません。
ちなみに今回は前者の「DBに保存されている文字列を表示」する想定です。
もしうまくいかなければconsole.logを仕込みつつご確認お願いしますm(__)m
1.文章内のURLを半角スペースで自動リンク化
まず、「文章内のURLを半角スペースで自動リンク化」する方法をご紹介します。
今回は半角スペースを入力することで、URLと判定させます。
ただ、半角スペースでURL判定させるとなると、結構色々と考慮することがあり手間です。。
URLと判定させたいパターンは以下です。(URLが青くリンク表示されている箇所)
半角スペースなしで、英数字のみで構成されるURLを自動的にリンクにする場合は、以下のサイトが参考になります。
自動リンクを適応させたい要素に「autoLinkSpace」等クラス名などを付けます。
<div class="autoLinkSpace">
◆文字+URL+文字の組み合わせ
前のみ半角スペース https://example.comテキスト
前後半角スペース https://example.com テキスト
URL後文字無し https://example.com
後ろのみ半角スペースhttps://example.com テキスト
</div>
<div class="autoLinkSpace">
// ...テキスト
</div>
改行(\n)が使用されている文字を、改行が反映されるようにCSSで調整します。
.autoLinkSpace {
word-wrap: break-word;
white-space: pre;
}
大まかな流れは、以下のような感じです。
- URLを自動判定したい要素「autoLinkSpace」をループ
- 各行に分割し、各行をループ(改行が、<br> なのか \n で割るのかは要変更)
- 2で分割した一行を、半角スペースで分割(例:[“テキスト”, “https://example.com”, ‘テキスト’])
- 3で分割した文字列の配列をループ
- httpが含まれれば、aタグに変換し文字列を結合する
$('.autoLinkSpace').each(function (index, element) {
// 要素内のメッセージ
let message = $(this).text();
// 行で分割する
let rows = message.split('\n');
// 各行を半角スペースで分割した文字の配列(例:["テキスト", "https://example.com", 'テキスト'])
let strings;
// aタグに変換したメッセージ
let joinString = '';
// 一行ずつループ
for (let i = 0; i < rows.length; i++) {
// 行にhttpが含まれていなければ処理を行わない
if (rows[i].indexOf('http') <= -1) {
if (rows[i] === '') {
joinString = joinString.concat('\n');
} else {
joinString = joinString.concat(rows[i], '\n');
}
continue;
}
// 文字列を半角スペースで分割
strings = rows[i].split(/\x20/);
for (let l = 0; l < strings.length; l++) {
// 文字+URLでURLの前に半角スペースがない場合は、URLと判定しない
if (strings[l].indexOf('http') === 0) {
let pattern = /(http.*$)/ig;
strings[l] = strings[l].replace(pattern, '<a href="$1" target="_blank">$1</a>');
}
joinString = joinString.concat(strings[l], ' ');
}
joinString = joinString.concat('\n');
}
$(this).html(joinString);
});
2.HTMLのaタグも一緒に使用できるようにする
aタグを使用する際に以下の<a>タグ内は変換しないようにしないといけないです。
URLと判定させたいパターンは以下です。(URLが青くリンク表示されている箇所)
<div class="autoLinkSpace">
◆文中のURL+aタグの組み合わせ
https://example.com <a href="https://example.com">【aタグのURLを使用https://example.com】</a>
<a href="https://example.com">【aタグのURLを使用https://example.com】</a> https://example.com <a href="https://example.com">【aタグのURLを使用https://example.com】</a>
</div>
先ほどのJavascriptに以下を追加します。
やっていることは、各行に<a>タグが使用されていれば処理を変えます。
<a>タグの判定は、row.match(<a(?:.+?)?>.*?<\/a>/g) で行います。
本当は<a href=”★https://example.com”>★https://example.com</a> <a>~</a>の間にある★URL以外のURLをリンクに変換するという風にしたかったのですが、正規表現が難しく、結局以下の3段階で変換するようにしました。
// 文頭のURL(URL+半角スペース+文字やタグ)をリンクにする
replaceString = rows[i].replace(/^((http.?)(?!(<\/a>)))\x20/ig, '$1 ');
// 文中のURL(文字やタグ+半角スペース+URL+半角スペース+文字やタグ)をリンクにする
replaceString = replaceString.replace(/\x20((http.?)(?!(<\/a>)))\x20/ig, ' $1 ');
// 末尾のURL(文字やタグ+半角スペース+URL)をリンクにする
replaceString = replaceString.replace(/\x20((http.*?$)(?!(<\/a>)))/ig, ' $1');
いいやり方をご存じの方はぜひ教えてください!m(__)m
// 行にaタグが使用されている場合
if (rows[i].match(/<a(?: .+?)?>.*?<\/a>/g) !== null) {
// 文頭のURL(URL+半角スペース+文字やタグ)をリンクにする
replaceString = rows[i].replace(/^((http.*?)(?!(<\/a>)))\x20/ig, '<a href="$1" target="_blank">$1</a> ');
// 文中のURL(文字やタグ+半角スペース+URL+半角スペース+文字やタグ)をリンクにする
replaceString = replaceString.replace(/\x20((http.*?)(?!(<\/a>)))\x20/ig, ' <a href="$1" target="_blank">$1</a> ');
// 末尾のURL(文字やタグ+半角スペース+URL)をリンクにする
replaceString = replaceString.replace(/\x20((http.*?$)(?!(<\/a>)))/ig, ' <a href="$1" target="_blank">$1</a>');
// 結合
joinString = joinString.concat(replaceString, '\n');
continue;
}
「1.文章内のURLを半角スペースで自動リンク化」と「2.HTMLのaタグも一緒に使用できるようにする」をあわせた、Javascript完成形はこちらです。
$('.autoLinkSpace').each(function (index, element) {
// 要素内のメッセージ
let message = $(this).text();
// 行で分割する
let rows = message.split('\n');
// 各行を半角スペースで分割した文字の配列(例:["テキスト", "https://example.com", 'テキスト'])
let strings;
// aタグに変換したメッセージ
let joinString = '';
// 一行ずつループ
for (let i = 0; i < rows.length; i++) {
// 行にhttpが含まれていなければ処理を行わない
if (rows[i].indexOf('http') <= -1) {
if (rows[i] === '') {
joinString = joinString.concat('\n');
} else {
joinString = joinString.concat(rows[i], '\n');
}
continue;
}
// 行にaタグが使用されている場合(「2.HTMLのaタグも一緒に使用できるようにする」)
if (rows[i].match(/<a(?: .+?)?>.*?<\/a>/g) !== null) {
// 文頭のURL(URL+半角スペース+文字やタグ)をリンクにする
replaceString = rows[i].replace(/^((http.*?)(?!(<\/a>)))\x20/ig, '<a href="$1" target="_blank">$1</a> ');
// 文中のURL(文字やタグ+半角スペース+URL+半角スペース+文字やタグ)をリンクにする
replaceString = replaceString.replace(/\x20((http.*?)(?!(<\/a>)))\x20/ig, ' <a href="$1" target="_blank">$1</a> ');
// 末尾のURL(文字やタグ+半角スペース+URL)をリンクにする
replaceString = replaceString.replace(/\x20((http.*?$)(?!(<\/a>)))/ig, ' <a href="$1" target="_blank">$1</a>');
// 結合
joinString = joinString.concat(replaceString, '\n');
continue;
}
// 文字列を半角スペースで分割(「1.文章内のURLを半角スペースで自動リンク化」)
strings = rows[i].split(/\x20/);
for (let l = 0; l < strings.length; l++) {
// 文字+URLでURLの前に半角スペースがない場合は、URLと判定しない
if (strings[l].indexOf('http') === 0) {
let pattern = /(http.*$)/ig;
strings[l] = strings[l].replace(pattern, '<a href="$1" target="_blank">$1</a>');
}
joinString = joinString.concat(strings[l], ' ');
}
joinString = joinString.concat('\n');
}
$(this).html(joinString);
});