nikkie-ftnextの日記

イベントレポートや読書メモを発信

reStructuredTextとリンクを作るマークアップ(全部一緒だと思っていたのですが、細かい意味の違いがあった…だと…)

はじめに

ずっとずっと、一緒だと思っていた。1 nikkieです。

reStructuredText(reST)にはいろんなマークアップがありますよね。
リンクを作りたいときは

`Link text <https://domain.invalid/>`_

と書いてきた2のですが、これが何をしているか何も分かっていなかったことをこのたび痛感しました。
一体何があったのか、共有していきます。

目次

reSTでリンクを作る書き方

私がこれまで知っていたリンクの書き方は次の2つです。

`Link text <https://domain.invalid/>`_
.. _Link text: https://domain.invalid/

`Link text`_

この2つの記法は同じようにリンクができるので、何も違いはないと思っていました。
今となっては「これらのマークアップ..の行など)が何をしているか」を全然理解していなかったなと感じます。

なおreSTでは、1行にURLだけを書いたり、インラインでURLを書いてもリンクとなります。 直接URLを書く記法については今回はスコープアウトし、リンクを作るマークアップについて見ていきます。

きっかけ:アンダースコア2つのreSTのリンク!?

reSTのリンクについて再インプットするきっかけとなったのはこちらのコミット。

`Link text <https://domain.invalid/>`_

というリンクを

`Link text <https://domain.invalid/>`__

アンダースコアが2個)と直していただいています。

これが何を意味するか、私、分からなかったんですよ。
というわけで、『Sphinxをはじめよう』🐊にあたってキャッチアップしました。

キャッチアップの結果、私は何も分かっていなかったことを知りました。

結論:リンクの記法まとめ

.. _Link text: https://domain.invalid/

`Link text`_
  • ..の行が「外部ハイパーリンクターゲット」の定義
  • ハイパーリンクターゲット」のリンクタイトル(ここではLink text)の末尾にアンダースコアを付けて、参照している
`Link text <https://domain.invalid/>`_
`Link text <https://domain.invalid/>`__
  • 2つのアンダースコアを付けた埋め込みURL記法は、ハイパーリンクターゲットを定義しない

これら3種類のほかにもう1つ「名前なしハイパーリンク」(後述)があります。

書き方が違うので、docutilsやSphinxにとっての意味も異なる(つまりビルド時の内部での扱いも異なる)はずですが、これらはリンクとしては同じになります。

Sphinxをはじめよう』付録Aより

ハイパーリンク記法

ハイパーリンク記法には次の2つがあります:

名前なしハイパーリンクで書くと以下のようになります。

.. __: https://domain.invalid/

`Link text`__

アンダースコア2つを使うことでハイパーリンクターゲットを定義しないので「名前なし」なのだと理解しました。

名前ありの方(ハイパーリンクターゲットを定義して参照)だと、一度定義したターゲットを何度も参照できます。

埋め込みURL記法

埋め込みURL記法も次のように2つあります:

前者では、..の行と同じようにハイパーリンクターゲットが定義されるので、何度も参照できます。

つまり(これまでの私がやっていたのですが)以下のように、アンダースコア1つの埋め込みURL記法を繰り返す

Awesome `Link text <https://domain.invalid/>`_ 😃

Fabulous `Link text <https://domain.invalid/>`_ 🤗

のではなく、

Awesome `Link text <https://domain.invalid/>`_ 😃

Fabulous `Link text`_ 🤗

と、初出時に定義したターゲットを参照する書き方ができるということです。
ターゲットを定義し(同時に参照し)ているので、定義は一度で十分というわけですね。

リンクのマークアップの理解度が低かったことで発生していた問題

登壇資料はsphinx-revealjsで作っていますが、これまで何のことかわからなかったSphinxのwarningがあります。

自己紹介のスライドには以下のように埋め込みURL記法で書いています:

* Twitter `@ftnext <https://twitter.com/ftnext>`_ / GitHub `@ftnext <https://github.com/ftnext>`_

この箇所で「Duplicate explicit target name」とwarningが出ます。

リンクの記法についてインプットした今なら分かります。
@ftnextという同名のハイパーリンクターゲットがあることを警告していたんですね!
このターゲットを参照することはないので、アンダースコア2つを使った埋め込みURL記法が適しているように思われます3

同様のことが上のコミットのリポジトリPython Boot Campランディングページ)でも起きていて、気づいた方が修正してくださったということですね。
ありがとうございます!

なお、warningが出ていましたが、リンクがあべこべになることはありませんでした(おそらく参照をしていたらあべこべになっていたと推測されます)。

知る機会はなかった?ー気づいていなかった!

SphinxやreSTは数年使ってきました4が、アンダースコア1つの埋め込みURL記法にしか気づいていませんでした。

「本当に知る機会はなかったのかな」と思い、手元の書籍を振り返ったところ、『Pythonプロフェッショナルプログラミング第3版』の7章 (p.189)にありました!

- `リンク文字列B <https://docs.sphinx-users.jp>`__

どうやらアンダースコア2本に気づかなかったようです。
「すでに知っているアンダースコア1つの書き方だな」と思ってしまったのですね。

終わりに

reSTのリンクのマークアップについて4つ見てきました(ハイパーリンク記法で2つ、埋め込みURL記法で2つ)。
ハイパーリンクターゲットを定義するかどうかの違いがあるのです!

これまでの私は他を知らなかったためにアンダースコア1つの埋め込みURL記法を多用(というか乱用?)してきました。
ただ、この書き方で定義したハイパーリンクターゲットを参照することはなく、私のユースケースにはアンダースコア2つの埋め込みURL記法のほうが適しているように思われます。

4つの方法を知りましたが、今後は少なくとも次の2つを使い分けていこうかなと今は考えています。

  • 複数回参照するリンク:ハイパーリンクターゲットを定義しておき、それを参照するハイパーリンク記法
  • 一度しか参照しないリンク:アンダースコア2つの埋め込みURL記法

P.S. sphinx-new-tab-linkはどの記法もサポートしています

自作したsphinx-new-tab-linkについてはこちらをどうぞ。

今回知ったことをテストコードに落とし、どの記法による外部リンクもブラウザの新しいタブで開けることを確認しました!
v0.1.1としてリリース🎉

今回紹介した書き方はガイドにも掲載しています(「対応している記法」セクション)。

新しく知ったリンクの記法だったり、それと合わせてsphinx-new-tab-linkを試したりしていただけたらとても嬉しいです!



  1. 今回の冒頭の一言は『リズと青い鳥』からです。"一緒"だと思っていたんですよ。『リズと青い鳥』公式サイト
  2. Sphinxのドキュメントに載っている例です。reStructuredText入門 — Sphinx documentation
  3. もしくはスライド全体で使えるように片方だけハイパーリンクターゲットとして定義してもいいかもしれません
  4. Sphinxを使って技術同人誌を書いたりもしてきました。イベントレポート | #技書博 2で初めて一人で執筆して頒布し、いただいたフィードバックから技術同人誌の楽しさを知りました - nikkie-ftnextの日記