-
Notifications
You must be signed in to change notification settings - Fork 44
/
Table.scala
180 lines (146 loc) · 5.58 KB
/
Table.scala
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package laika.ast
/** A table consisting of a head and a body part and optional caption and column specification.
*/
case class Table(
head: TableHead,
body: TableBody,
caption: Caption = Caption(),
columns: Columns = Columns(Nil),
options: Options = Options.empty
) extends Block
with ElementTraversal with RewritableContainer {
type Self = Table
def rewriteChildren(rules: RewriteRules): Table = copy(
head = head.rewriteChildren(rules),
body = body.rewriteChildren(rules),
caption = caption.rewriteChildren(rules)
)
override def toString: String = FormattedElementString.render(this)
def withOptions(options: Options): Table = copy(options = options)
}
object Table {
/** Creates a table without header rows, all specified rows will
* be treated as rows of the table body.
*/
def apply(row: Row, rows: Row*): Table = Table(TableHead(Nil), TableBody(row +: rows.toList))
}
/** A table element, like a row, cell or column.
*/
sealed trait TableElement extends Element { type Self <: TableElement }
/** A container of table elements.
*/
sealed trait TableContainer extends TableElement with ElementContainer[TableElement] {
type Self <: TableContainer
}
/** Contains the header rows of a table.
*/
case class TableHead(content: Seq[Row], options: Options = Options.empty) extends TableElement
with TableContainer with RewritableContainer {
type Self = TableHead
def rewriteChildren(rules: RewriteRules): TableHead =
copy(content = content.map(_.rewriteChildren(rules)))
def withOptions(options: Options): TableHead = copy(options = options)
}
/** Contains the body rows of a table.
*/
case class TableBody(content: Seq[Row], options: Options = Options.empty) extends TableElement
with TableContainer with RewritableContainer {
type Self = TableBody
def rewriteChildren(rules: RewriteRules): TableBody =
copy(content = content.map(_.rewriteChildren(rules)))
def withOptions(options: Options): TableBody = copy(options = options)
}
/** The table caption.
*/
case class Caption(content: Seq[Span] = Nil, options: Options = Options.empty) extends TableElement
with SpanContainer {
type Self = Caption
def withContent(newContent: Seq[Span]): Caption = copy(content = newContent)
def withOptions(options: Options): Caption = copy(options = options)
}
object Caption extends SpanContainerCompanion {
type ContainerType = Caption
protected def createSpanContainer(spans: Seq[Span]): Caption = Caption(spans)
}
/** Contains the (optional) column specification of a table.
*/
case class Columns(content: Seq[Column], options: Options = Options.empty) extends TableElement
with TableContainer {
type Self = Columns
def withOptions(options: Options): Columns = copy(options = options)
}
/** Convenient factory for creating a `Columns` instance based on the options
* for the individual columns.
*/
object Columns {
def options(options: Options*): Columns = Columns(options.map(Column.apply))
}
/** The options (like styles) for a column table.
*/
case class Column(options: Options = Options.empty) extends TableElement {
type Self = Column
def withOptions(options: Options): Column = copy(options = options)
}
/** A single table row. In case some of the previous rows contain
* cells with a colspan greater than 1, this row may contain
* fewer cells than the number of columns in the table.
*/
case class Row(content: Seq[Cell], options: Options = Options.empty) extends TableElement
with TableContainer with RewritableContainer {
type Self = Row
def rewriteChildren(rules: RewriteRules): Row =
copy(content = content.map(_.rewriteChildren(rules)))
def withOptions(options: Options): Row = copy(options = options)
}
object Row {
def apply(cell: Cell, cells: Cell*): Row = Row(cell +: cells.toList)
}
/** A single cell, potentially spanning multiple rows or columns, containing
* one or more block elements.
*/
case class Cell(
cellType: CellType,
content: Seq[Block],
colspan: Int = 1,
rowspan: Int = 1,
options: Options = Options.empty
) extends TableElement
with BlockContainer {
type Self = Cell
def withContent(newContent: Seq[Block]): Cell = copy(content = newContent)
def withOptions(options: Options): Cell = copy(options = options)
}
/** The cell type specifies which part of the table the cell belongs to.
*/
sealed abstract class CellType
object CellType {
/** A cell in the head part of the table.
*/
case object HeadCell extends CellType with BlockContainerCompanion {
type ContainerType = Cell
def apply(blocks: Seq[Block]): Cell = Cell(this, blocks)
protected def createBlockContainer(blocks: Seq[Block]) = Cell(this, blocks)
}
/** A cell in the body part of the table.
*/
case object BodyCell extends CellType with BlockContainerCompanion {
type ContainerType = Cell
def apply(blocks: Seq[Block]): Cell = Cell(this, blocks)
protected def createBlockContainer(blocks: Seq[Block]) = Cell(this, blocks)
}
}