AsciiDocの表(Table)のcols属性の仕様&Asciidoctorの内部実装について調べてみた のセル版。
参考サイト1 Asciidoctor User Manual #cell に割と詳しく書いてありそう。
セル結合の記述例
セル(|
で始まる)の直前で指定する。下記の例でいうと、.2+^.^
や 3+^
の部分。
AsciiDoc
[options="header"]
|===
|Date |Duration | Location | Plan
.2+^.^|2021.01.04 |08:00 | XXX | game
|09:00 | YYY | coding
|2021.01.05 |08:00 | XXX | no plan
|2021.01.06 3+^| work
|===
内部実装を追う
parser.rb の self.parse_table
メソッドから呼ばれている parse_cellspec
メソッド
parser.rb(抜粋&行番号補足)
# Internal: Parse the cell specs for the current cell.
#
# The cell specs dictate the cell's alignments, styles or filters,
# colspan, rowspan and/or repeating content.
#
# The default spec when pos == :end is {} since we already know we're at a
# delimiter. When pos == :start, we *may* be at a delimiter, nil indicates
# we're not.
#
# returns the Hash of attributes that indicate how to layout
# and style this cell in the table.
def self.parse_cellspec(line, pos = :end, delimiter = nil) # 1
m, rest = nil, '' # 2
# 3
if pos == :start # 4
if line.include? delimiter # 5
spec_part, delimiter, rest = line.partition delimiter # 6
if (m = CellSpecStartRx.match spec_part) # 7
return [{}, rest] if m[0].empty? # 8
else # 9
return [nil, line] # 10
end # 11
else # 12
return [nil, line] # 13
end # 14
else # pos == :end # 15
if (m = CellSpecEndRx.match line) # 16
# NOTE return the line stripped of trailing whitespace if no cellspec is found in this case # 17
return [{}, line.rstrip] if m[0].lstrip.empty? # 18
rest = m.pre_match # 19
else # 20
return [{}, line] # 21
end # 22
end # 23
# 24
spec = {} # 25
if m[1] # 26
colspec, rowspec = m[1].split '.' # 27
colspec = colspec.nil_or_empty? ? 1 : colspec.to_i # 28
rowspec = rowspec.nil_or_empty? ? 1 : rowspec.to_i # 29
if m[2] == '+' # 30
spec['colspan'] = colspec unless colspec == 1 # 31
spec['rowspan'] = rowspec unless rowspec == 1 # 32
elsif m[2] == '*' # 33
spec['repeatcol'] = colspec unless colspec == 1 # 34
end # 35
end # 36
# 37
if m[3] # 38
colspec, rowspec = m[3].split '.' # 39
if !colspec.nil_or_empty? && TableCellHorzAlignments.key?(colspec) # 40
spec['halign'] = TableCellHorzAlignments[colspec] # 41
end # 42
if !rowspec.nil_or_empty? && TableCellVertAlignments.key?(rowspec) # 43
spec['valign'] = TableCellVertAlignments[rowspec] # 44
end # 45
end # 46
# 47
if m[4] && TableCellStyles.key?(m[4]) # 48
spec['style'] = TableCellStyles[m[4]] # 49
end # 50
# 51
[spec, rest] # 52
end # 53
7行目および16行目でマッチング処理をしている。使用している正規表現は下記。
rx.rb(抜粋&コメント一部省略&補足)
# Examples
# 2.3+<.>m
# m[1] m[2] m[3] m[4]
# <---------------------------><----> <-------------------------------------> <----->
CellSpecStartRx = /^[ \t]*(?:(\d+(?:\.\d*)?|(?:\d*\.)?\d+)([*+]))?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?([a-z])?$/
CellSpecEndRx = /[ \t]+(?:(\d+(?:\.\d*)?|(?:\d*\.)?\d+)([*+]))?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?([a-z])?$/
CellSpecStartRx
は行頭用、CellSpecEndRx
はそれ以外用っぽい。
- m[1]m[2]:
整数
.
整数
+
の場合・・・
結合する列数(横方向)と結合する行数(縦方向)。.
以降を省略可。もしくは、.
の前を省略することもできる。 - m[1]m[2]:
整数
*
の場合・・・ 指定した列数だけ同じセルを繰り返す(参考サイト1参照)。 - m[3]:横方向(
<
or^
or>
).
縦方向(<
or^
or>
)・・・ アライメント 横(左寄せ、中央寄せ、右寄せ) と 縦(上寄せ、中央寄せ、下寄せ)。.
以降を省略可。もしくは、.
の前を省略することもできる。 - m[4]:
文字
・・・書式指定