reStructuredTextの箇条書きの注意点
概要
reStructuredText(以下、RST)はマークアップ言語の一つであり、ドキュメント生成ツールであるSphinxをはじめとして、さまざまな場面で使われている。 RSTには箇条書きを表現する構文があるが、いくつかの注意点がある。
導入
まずは導入として、箇条書きについて簡単に説明する。
以下のように、各行の先頭をすべてアスタリスク(*)とスペース( )で始めることで、それぞれの行を項目とした箇条書きとなる。
アスタリスクの代わりにプラス(+)、マイナス(-)を用いても良い。
* 項目1
* 項目2
* 項目3
また、ネストされた箇条書きにも対応している。
* 項目1
* 項目1-1
* 項目1-2
* 項目2
* 項目2-1
* 項目2-2
* 項目3
今回のエントリでは、RSTの箇条書きの構文における注意点をいくつか示す。
例1
まずは、空行に関する注意点である。たとえば、以下のような書き方は正しくない。「行1」と「項目1」の間に空行がないためである。
行1
* 項目1
* 項目2
* 項目3
この構造は正しく認識されず、Sphinxによって変換したとき、誤った出力となる(アスタリスクが文章中の単なる文字として出力される)。 その上、Sphinxが警告を発することもないため、特に注意が必要である。
例2
また、後ろにも空行が必要である。そのため、以下のような書き方は正しくない。
* 項目1
* 項目2
* 項目3
行2
ただしこれはSphinxによって警告が出力される上、一応正しく認識・描画される。
例3
ネストされた箇条書きの子要素に対しても、同様のことが言える。つまり、以下のような書き方は正しくない上、Sphinxが誤った出力をする。
* 項目1
* 項目1-1
* 項目1-2
* 項目2
* 項目3
例4
こちらは箇条書きの子要素の後ろの空行がないパターンである。これは、警告が出力されず、正しく認識されるが、一貫性の観点から好ましい書き方ではない。
* 項目1
* 項目1-1
* 項目1-2
* 項目2
* 項目3
例5
さて、これはここまでの例とは違って、インデントに関する注意点である。以下のような書き方は正しくない。 なぜなら、ネストされた箇条書きの子項目のアスタリスクは、親要素の内容とインデントを揃える必要があるためである。 ここでは「項目1-1」のアスタリスクは「項目1」と同じインデント、つまりちょうど2つのスペースが先頭になくてはならない。
* 項目1
* 項目1-1
* 項目1-2
* 項目2
* 項目3
これもまた、Sphinxが警告を発することなく誤った構造が出力される(子項目が「引用部分(blockquote)」として認識される)。
箇条書きの構造について
RSTフォーマットでは、箇条書きのそれぞれの要素が複数行となることができる。
* 項目1の1行目
項目1の2行目
項目1の3行目
* 項目2の1行目
項目2の2行目
項目2の3行目
ネストされた箇条書きは、この機能を利用したものである。ふたたび、以下の構造を考える。
* 項目1
* 項目1-1
* 項目1-2
* 項目2
* 項目3
この構造は、3つの項目からなる箇条書きである。2つめと3つめの内容はそれぞれ「項目2」と「項目3」であり、 1つめの項目の内容は、以下に示す複数行全体である。
項目1
* 項目1-1
* 項目1-2
つまり、箇条書きの中には任意の構造を入れることができて、上の例ではたまたまそれがもう一つの箇条書きである、ということである。 そのため、厳密に言えば、「ネストされた箇条書き」という構造があるわけではない。
以上によって、例3・例4・例5の挙動が統一的に理解できる。 例3は例1の構造が箇条書きの内部に入っているだけであり、特に説明は不要だろう。 例4が警告なしに動作するのは、「項目2」の行がネストされた内側の箇条書きではなく、外側の箇条書きの2つめの項目だからである。 つまり、空行がなくても「項目2」が箇条書き部分の続きとみなされることはない。
例5については、1つめの項目の内容は以下のようになる。
項目1
* 項目1-1
* 項目1-2
これは、段落全体がインデントされている状態であり、RSTにおける引用(blockquote)のマークアップそのものである。 そのため、Sphinxがこれを引用と認識するのは当然である。
終わりに
以上で挙げた注意点を見落とすと、一見正しい構造に見えるRSTテキストをSphinxでHTMLに変換したときに、意図通りの構造とならないなどの問題が発生する。 特に、Sphinxが警告を出さないケースは発見が難しいため、注意が必要となる。 実際、Numpyの公式ドキュメントでまさにこの問題を踏み抜いている箇所があり、HTMLの表示が崩れていた(Issueとして報告済み)。