7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

List continuationでAsciidoctorの順序付きリストの採番を崩さないようにする

Last updated at Posted at 2018-06-17

はじめに

マークアップ言語で手順を記述する際に順序付きリストは便利ですよね。
しかし、代表的なマークアップ言語であるMarkdownでは、順序付きリストの間にコードブロックやテーブルを挿入すると採番が1から振り直されてしまうという悲しみを背負っています。
一方で、Asciidoctorというマークアップ言語にはそのような悲しみを克服するList continuationという機能が用意されています。
本記事では、List continuation機能で順序付きリストの採番を崩さないようにする例を紹介します。

環境情報

$ asciidoctor --version
Asciidoctor 1.5.6.2 [http://asciidoctor.org]
Runtime Environment (ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-darwin17]) (lc:UTF-8 fs:UTF-8 in:- ex:UTF-8)

List continuation とは

まず、公式の説明を引用させていただきます。

To add additional paragraphs or other block elements to a list item, you must “attach” them (in a series) using a list continuation. A list continuation is a + symbol on a line by itself, immediately adjacent to the block being attached.

block とは Asciidoctor の文書を構成する要素です。例えば、以下は block です。

  • コードブロック
  • パラグラフ

つまり、表やコードブロックなどを含めてリストの1項目とする機能です。

NG例

最初に、順序付きリストの採番が崩れてしまう例を示します。
コードは以下です。

. foo
|===
||0|1
|0|0|1
|1|1|0
|===

. bar

. baz

表示は以下です。

スクリーンショット 2018-06-17 14.12.40.png

barに1が採番されてしまいました。

List continuationで採番を崩さない例

次に、順序付きリストの採番を崩さない例を示します。
コードは以下です(2行目に+が追加されただけです)。

. foo
+
|===
||0|1
|0|0|1
|1|1|0
|===

. bar

. baz

表示は以下です。

スクリーンショット 2018-06-17 14.08.00.png

barにきちんと2が採番されました。
図、コードブロック、パラグラフも同様に採番を崩さないようにできます。

少しマニアックなおまけ

Asciidoctorは文書に属性(環境変数のようなもの)を定義する機能があります。
例えば、以下のコードは pi という属性に 3.14 をセットし、それを参照した文を表示させています。

:pi: 3.14
. 円の半径 `r` を測ります。
. 円の面積 `S = {pi} * r * r` を計算します。
. 円の円周 `L = 2 * {pi} * r` を求めます。

表示は以下です。

スクリーンショット 2018-06-17 14.28.14.png

上記のように記述することで、円周率を 3 として計算させるように変更する際、1行目の属性 pi の値を変更するだけでよくなります。

さて、稀なケースではありますが、属性の定義を順序付きリストの中に組み込みたい場合があります。
あまりうまい例ではないですが、以下のコードを考えます。

. 小数部分 `r` と 次数 `n` を標準入力で受け取ります。

ifeval::[{precise} == true]
. 2次の項まで近似します、というメッセージを標準出力します。
:expr: 1 + nr + n(n-1)/2*r*r
endif::[]
ifeval::[{precise} == false]
. 1次の項まで近似します、というメッセージを標準出力します。
:expr: 1 + nr
endif::[]

. `y = {expr}` を求めます。

. `y` を標準出力します。

上記は属性 precisetrue ならば2次の項まで近似する項目を、 false ならば1次の項まで近似する項目を表示させたかったコードです(ちなみに、 ifeval は想像の通り、条件分岐文です)。
しかし、以下のように属性の定義式がそのまま表示され、属性の定義もされていません( precisetrue とします)。

スクリーンショット 2018-06-17 14.59.12.png

これもList continuationすれば解決するのか?と思い、以下のコードにしてみます(属性の定義式の前の行に+を追加した)。

. 小数部分 `r` と 次数 `n` を標準入力で受け取ります。

ifeval::[{precise} == true]
. 2次の項まで近似します、というメッセージを標準出力します。
+
:expr: 1 + nr + n(n-1)/2*r*r
endif::[]
ifeval::[{precise} == false]
. 1次の項まで近似します、というメッセージを標準出力します。
+
:expr: 1 + nr
endif::[]

. `y = {expr}` を求めます。

. `y` を標準出力します。

以下のように属性の定義式は表示されなくなりましたが、属性は定義されていないままです。

スクリーンショット 2018-06-17 15.04.21.png

リストの中で属性の定義はできないのでしょうか。
実は、以下のようにインラインで属性を定義することで実現できます。

. 小数部分 `r` と 次数 `n` を標準入力で受け取ります。

ifeval::[{precise} == true]
. 2次の項まで近似します、というメッセージを標準出力します。
{set:expr:1 + nr + n(n-1)/2 r*r}
endif::[]
ifeval::[{precise} == false]
. 1次の項まで近似します、というメッセージを標準出力します。
{set:expr:1 + nr}
endif::[]

. `y = {expr}` を求めます。

. `y` を標準出力します。

出力は以下のとおりです。

スクリーンショット 2018-06-17 15.06.29.png

期待通りの結果が得られました。
これは、属性の定義式がブロックでないことに起因すると思われます。

参考ページ

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?