我检查了如何指定AsciiDoc表的单元格属性和Asciidoctor的内部实现的规范


AsciiDoc的表(Table)的单元格版本具有cols属性规范和Asciidoctor的内部实现。

参考站点1 Asciidoctor用户手册#cell似乎有相对详细的描述。

单元合并的描述示例

立即在

单元格之前指定(从|开始)。在下面的示例中,.2+^.^3+^部分。

AsciiDoc

1
2
3
4
5
6
7
8
[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
|===

的输出如下。
image.png

遵循内部实施

parser.rb的self.parse_table方法调用的parse_cellspec方法

parser.rb(节选和行号补充)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# 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(节选和注释省略和补充)

1
2
3
4
5
6
# 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]:水平(<^>).垂直(<^>)???水平对齐(左对齐,居中对齐,右对齐))和垂直(顶部,中心,底部)。 .和更高版本可以省略。或者,可以省略.之前的部分。
  • m [4]:文字 ???格式规范

参考网站

  • Asciidoctor用户手册#cell
  • AsciiDoc速查表