Markdown において自動的にリンクを作成する記法(以下、自動リンクと呼称)には、以下のような 3 つの記法がある。
-
http:
等から始まる生の URL リンク -
http:
等から始まる URL を<
~>
で囲うリンク -
@
によるユーザーへのリンク -
#
によるタグへのリンク
これらが Markdown 記法による以下のような手動リンクの表示テキスト (displayed text
) 内に含まれていた場合、どちらのリンクが優先されるのか検証してみたい。
[displayed text](URI/address "link title")
^^^^^^^^^^^^^^
↑ ここに自動的に作成されるリンクを挿入する
■ 背景
CommonMark によるリンクの仕様では、「リンクが入れ子になっている場合には内側のリンクが優先されるExample 517」ようになっている。
[Example Domain [Qiita](https://qiita.com) ](https://www.example.com)
^^^^^^^^^^^^^^^^^^^^^^^^^
↑ ここはリテラルに表示される
[Example Domain [Qiita][qiita] ](https://www.example.com)
^^^^^^^^^^^^^^^^^^^^^^^^^
↑ ここはリテラルに表示される
[qiita]: https://qiita.com
[Example Domain Qiita ](https://www.example.com)
[Example Domain Qiita ](https://www.example.com)
では、自動リンクが表示テキスト内に挿入された場合はどのようになるのでしょうか。
■ 検証
具体的に次のようなリンクを作成した場合、どのような表示となるか検証してみたい。
-
http:
等から始まる生の URL リンク[https://qiita.com](https://www.example.com)
-
http:
等から始まる URL を<
~>
で囲うリンク[<https://qiita.com>](https://www.example.com)
-
@
によるユーザーへのリンク[@Qiita](https://www.example.com)
-
#
によるタグへのリンク[#1](https://www.example.com)
どうなると思いますか?
少しだけおもしろい結果を得ます。
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
■ 結果
Qiita では次のような結果を得ました。(ただし、#
によるタグリンクは作成されません)
-
http:
等から始まる生の URL リンク[https://qiita.com](https://www.example.com)
-
http:
等から始まる URL を<
~>
で囲うリンク[<https://qiita.com>](https://www.example.com)
-
@
によるユーザーへのリンク[@Qiita](https://www.example.com)
-
#
によるタグへのリンク[#1](https://www.example.com)
一見すると、どのリンクも期待した通りのスタイルで表示されており、手動リンクの表示が壊れていない。と言うことは、表示テキスト内のリンクになる文字列はリテラルに解釈され、https://www.example.com のリンクが貼られていると考えられる。
では、マウスポインタをホバーしたりロングタップして、実際に遷移するリンクを確認してほしい。
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
表示テキスト内に <
~>
で囲われた自動リンクを挿入した場合、遷移するリンク先は https://qiita.com だぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁ!!!
▽ 新たな疑問
<
~>
で囲われた自動リンクは CommonMark で仕様が決定されているが、この自動リンクは次のように手動リンクと等価なものとして解釈できる。(HTML へのパース結果が等価に示されているため Example 482, Example 593)
<https://qiita.com>
⇅
[https://qiita.com](https://qiita.com)
すなわち、感覚としては次のような状態と考えることが出来る。このリンクは内側のリンクがリンクとして解釈され、外側のリンクは壊れる。
[[https://qiita.com](https://qiita.com)](https://www.example.com)
[https://qiita.com](https://www.example.com)
しかし、<
~>
で囲われた自動リンクが表示テキスト内にある場合、自動リンクが優先され、手動リンクはどこかへ消えてしまう。どこへ……???
▽ 行方の捜索
[<https://qiita.com>](https://www.example.com)
において、https://www.example.com
のリンクの行方を探してみたい。
commonmark.js のデモから HTML を表示させてみる ⧉ と、次のようにパースされていることが分かる。(直接の関係がないため <p>
タグを意図的に消しています)
<a href="https://www.example.com"><a href="https://qiita.com">https://qiita.com</a></a>
実は、以下のような Markdown リンクを作成すると https://www.example.com
がどこへ行ったのか分かる。
[Example <https://qiita.com>](https://www.example.com)
↓
<a href="https://www.example.com">Example <a href="https://qiita.com">https://qiita.com</a></a>
“Example ” は https://www.example.com へのリンクとなっている。
すなわち、[<https://qiita.com>](https://www.example.com)
では、https://www.example.com
のリンクを埋め込む文字列がない状態となっていたために、行方不明になっていたようだ。
また、[
~]
で囲われた <https://qiita.com>
の前後に文字列を挿入すると、不思議なことが起こる。
[Example <https://qiita.com> Domain](https://www.example.com)
Example https://qiita.com Domain
<https://qiita.com>
の左側の文字列 (Example
) にはリンクが埋め込まれるのに対して、右側の文字列 (Domain
) にはリンクが埋め込まれない。commonmark.js でのデモであっても、次のような HTML にパースしている。⧉
<a href="https://www.example.com">Example <a href="https://qiita.com">https://qiita.com</a> Domain</a>
ふしぎ
▽ a
要素の仕様
HTML の仕様では、a
要素は a
要素そのものを含むことのできないトランスペアレントな要素です。⧉
そのため、a
要素そのものが入れ子になっているリンクは不正な構造として、ブラウザが以下のように修正します。
<a><a>This is link!</a></a>
<!-- 入れ子になっている -->
⇓
<a></a><a>This is link!</a></a>
<!-- 2 つのリンクが並んでいるが、最右に不要な終了タグが残されている -->
ただし、末尾に不要な </a>
が残ってしまいます。これもブラウザ側が無視することで、実質的には以下のように解釈されます。
<a></a><a>This is link!</a>
<!-- 2 つのリンクが並んでいる -->
このことを踏まえると、先に示した以下の例では、次のような処理がなされていることが分かります。
[Example <https://qiita.com> Domain](https://www.example.com)
-
Markdown から HTML に変換される
<a href="https://www.example.com">Example <a href="https://qiita.com">https://qiita.com</a> Domain</a>
-
a
要素そのものが入れ子になっているため、内側の<a>
の前に</a>
が入る<a href="https://www.example.com">Example </a><a href="https://qiita.com">https://qiita.com</a> Domain</a>
-
末尾にある不要な
</a>
が無視される<a href="https://www.example.com">Example </a><a href="https://qiita.com">https://qiita.com</a> Domain
このような処理のために、Domain
はリンクのない文字列になっていたのでした。
まとめ
リンクは URL で表示されていれば安心して遷移して良いものではない。出来るならば、URL ウィンドウを確認した方が望ましいだろう。
“<a>
nested in <a>
” のときのリンクの挙動はどのように規定されているのだろう。知っている人がいたら教えてほしい。
ちなみに、この挙動は GitHub Markdown でも同じものとして確認することが出来た。
検証用(折りたたみ)
[https://qiita.com](https://www.example.com)
[<https://qiita.com>](https://www.example.com)
[@Qiita](https://www.example.com)
[#1](https://www.example.com)
追記
2023/01/16: 軽微修正。
2025/07/19: a
要素の仕様に関する追記。