Add table pretty printing & alignment
Also dismissed implementing colgroups for now - had it but didn't like the added complexity for a very questionable benefit - i've actually never used that feature of org tables...
This commit is contained in:
parent
c08119bbc8
commit
f28f400d7e
10 changed files with 261 additions and 113 deletions
|
@ -8,8 +8,6 @@ A basic org-mode parser in go
|
||||||
- support more keywords: https://orgmode.org/manual/In_002dbuffer-settings.html
|
- support more keywords: https://orgmode.org/manual/In_002dbuffer-settings.html
|
||||||
- #+LINK
|
- #+LINK
|
||||||
- #+INCLUDE
|
- #+INCLUDE
|
||||||
- table colgroups https://orgmode.org/worg/org-tutorials/tables.html
|
|
||||||
- table pretty printing
|
|
||||||
*** TODO [[https://github.com/chaseadamsio/goorgeous/issues/10][#10]]: Support noexport
|
*** TODO [[https://github.com/chaseadamsio/goorgeous/issues/10][#10]]: Support noexport
|
||||||
*** TODO [[https://github.com/chaseadamsio/goorgeous/issues/31][#31]]: Support #+INCLUDE
|
*** TODO [[https://github.com/chaseadamsio/goorgeous/issues/31][#31]]: Support #+INCLUDE
|
||||||
- see https://orgmode.org/manual/Include-files.html
|
- see https://orgmode.org/manual/Include-files.html
|
||||||
|
|
|
@ -104,3 +104,7 @@ figcaption {
|
||||||
background-color: #ccc; }
|
background-color: #ccc; }
|
||||||
.footnote-definition .footnote-body p:only-child {
|
.footnote-definition .footnote-body p:only-child {
|
||||||
margin: 0.2em 0; }
|
margin: 0.2em 0; }
|
||||||
|
|
||||||
|
.align-left { text-align: left; }
|
||||||
|
.align-center { text-align: center; }
|
||||||
|
.align-right { text-align: right; }
|
||||||
|
|
57
org/html.go
57
org/html.go
|
@ -84,12 +84,6 @@ func (w *HTMLWriter) writeNodes(ns ...Node) {
|
||||||
|
|
||||||
case Table:
|
case Table:
|
||||||
w.writeTable(n)
|
w.writeTable(n)
|
||||||
case TableHeader:
|
|
||||||
w.writeTableHeader(n)
|
|
||||||
case TableRow:
|
|
||||||
w.writeTableRow(n)
|
|
||||||
case TableSeparator:
|
|
||||||
w.writeTableSeparator(n)
|
|
||||||
|
|
||||||
case Paragraph:
|
case Paragraph:
|
||||||
w.writeParagraph(n)
|
w.writeParagraph(n)
|
||||||
|
@ -283,34 +277,39 @@ func (w *HTMLWriter) writeNodeWithMeta(n NodeWithMeta) {
|
||||||
|
|
||||||
func (w *HTMLWriter) writeTable(t Table) {
|
func (w *HTMLWriter) writeTable(t Table) {
|
||||||
w.WriteString("<table>\n")
|
w.WriteString("<table>\n")
|
||||||
w.writeNodes(t.Header)
|
beforeFirstContentRow := true
|
||||||
w.WriteString("<tbody>\n")
|
for i, row := range t.Rows {
|
||||||
w.writeNodes(t.Rows...)
|
if row.IsSpecial || len(row.Columns) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if beforeFirstContentRow {
|
||||||
|
beforeFirstContentRow = false
|
||||||
|
if i+1 < len(t.Rows) && len(t.Rows[i+1].Columns) == 0 {
|
||||||
|
w.WriteString("<thead>\n")
|
||||||
|
w.writeTableColumns(row.Columns, "th")
|
||||||
|
w.WriteString("</thead>\n<tbody>\n")
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
w.WriteString("<tbody>\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.writeTableColumns(row.Columns, "td")
|
||||||
|
}
|
||||||
w.WriteString("</tbody>\n</table>\n")
|
w.WriteString("</tbody>\n</table>\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *HTMLWriter) writeTableRow(t TableRow) {
|
func (w *HTMLWriter) writeTableColumns(columns []Column, tag string) {
|
||||||
w.WriteString("<tr>\n")
|
w.WriteString("<tr>\n")
|
||||||
for _, column := range t.Columns {
|
for _, column := range columns {
|
||||||
w.WriteString("<td>")
|
if column.Align == "" {
|
||||||
w.writeNodes(column...)
|
w.WriteString(fmt.Sprintf("<%s>", tag))
|
||||||
w.WriteString("</td>")
|
} else {
|
||||||
|
w.WriteString(fmt.Sprintf(`<%s class="align-%s">`, tag, column.Align))
|
||||||
|
}
|
||||||
|
w.writeNodes(column.Children...)
|
||||||
|
w.WriteString(fmt.Sprintf("</%s>\n", tag))
|
||||||
}
|
}
|
||||||
w.WriteString("\n</tr>\n")
|
w.WriteString("</tr>\n")
|
||||||
}
|
|
||||||
|
|
||||||
func (w *HTMLWriter) writeTableHeader(t TableHeader) {
|
|
||||||
w.WriteString("<thead>\n")
|
|
||||||
for _, column := range t.Columns {
|
|
||||||
w.WriteString("<th>")
|
|
||||||
w.writeNodes(column...)
|
|
||||||
w.WriteString("</th>")
|
|
||||||
}
|
|
||||||
w.WriteString("\n</thead>\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *HTMLWriter) writeTableSeparator(t TableSeparator) {
|
|
||||||
w.WriteString("<tr></tr>\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func withHTMLAttributes(input string, kvs ...string) string {
|
func withHTMLAttributes(input string, kvs ...string) string {
|
||||||
|
|
73
org/org.go
73
org/org.go
|
@ -41,6 +41,12 @@ func (w *OrgWriter) emptyClone() *OrgWriter {
|
||||||
return &wcopy
|
return &wcopy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *OrgWriter) nodesAsString(nodes ...Node) string {
|
||||||
|
tmp := w.emptyClone()
|
||||||
|
tmp.writeNodes(nodes...)
|
||||||
|
return tmp.String()
|
||||||
|
}
|
||||||
|
|
||||||
func (w *OrgWriter) writeNodes(ns ...Node) {
|
func (w *OrgWriter) writeNodes(ns ...Node) {
|
||||||
for _, n := range ns {
|
for _, n := range ns {
|
||||||
switch n := n.(type) {
|
switch n := n.(type) {
|
||||||
|
@ -65,12 +71,6 @@ func (w *OrgWriter) writeNodes(ns ...Node) {
|
||||||
|
|
||||||
case Table:
|
case Table:
|
||||||
w.writeTable(n)
|
w.writeTable(n)
|
||||||
case TableHeader:
|
|
||||||
w.writeTableHeader(n)
|
|
||||||
case TableRow:
|
|
||||||
w.writeTableRow(n)
|
|
||||||
case TableSeparator:
|
|
||||||
w.writeTableSeparator(n)
|
|
||||||
|
|
||||||
case Paragraph:
|
case Paragraph:
|
||||||
w.writeParagraph(n)
|
w.writeParagraph(n)
|
||||||
|
@ -206,34 +206,45 @@ func (w *OrgWriter) writeListItem(li ListItem) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *OrgWriter) writeTable(t Table) {
|
func (w *OrgWriter) writeTable(t Table) {
|
||||||
w.writeNodes(t.Header)
|
for _, row := range t.Rows {
|
||||||
w.writeNodes(t.Rows...)
|
w.WriteString(w.indent)
|
||||||
}
|
if len(row.Columns) == 0 {
|
||||||
|
w.WriteString(`|`)
|
||||||
|
for i := 0; i < len(t.ColumnInfos); i++ {
|
||||||
|
w.WriteString(strings.Repeat("-", t.ColumnInfos[i].Len+2))
|
||||||
|
if i < len(t.ColumnInfos)-1 {
|
||||||
|
w.WriteString("+")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.WriteString(`|`)
|
||||||
|
|
||||||
func (w *OrgWriter) writeTableHeader(th TableHeader) {
|
} else {
|
||||||
w.writeNodes(th.SeparatorBefore)
|
w.WriteString(`|`)
|
||||||
w.writeTableColumns(th.Columns)
|
for _, column := range row.Columns {
|
||||||
w.writeNodes(th.SeparatorAfter)
|
w.WriteString(` `)
|
||||||
}
|
content := w.nodesAsString(column.Children...)
|
||||||
|
if content == "" {
|
||||||
func (w *OrgWriter) writeTableRow(tr TableRow) {
|
content = " "
|
||||||
w.writeTableColumns(tr.Columns)
|
}
|
||||||
}
|
n := column.Len - len(content)
|
||||||
|
if n < 0 {
|
||||||
func (w *OrgWriter) writeTableSeparator(ts TableSeparator) {
|
n = 0
|
||||||
w.WriteString(w.indent + ts.Content + "\n")
|
}
|
||||||
}
|
if column.Align == "center" {
|
||||||
|
if n%2 != 0 {
|
||||||
func (w *OrgWriter) writeTableColumns(columns [][]Node) {
|
w.WriteString(" ")
|
||||||
w.WriteString(w.indent + "| ")
|
}
|
||||||
for i, columnNodes := range columns {
|
w.WriteString(strings.Repeat(" ", n/2) + content + strings.Repeat(" ", n/2))
|
||||||
w.writeNodes(columnNodes...)
|
} else if column.Align == "right" {
|
||||||
w.WriteString(" |")
|
w.WriteString(strings.Repeat(" ", n) + content)
|
||||||
if i < len(columns)-1 {
|
} else {
|
||||||
w.WriteString(" ")
|
w.WriteString(content + strings.Repeat(" ", n))
|
||||||
|
}
|
||||||
|
w.WriteString(` |`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
w.WriteString("\n")
|
||||||
}
|
}
|
||||||
w.WriteString("\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *OrgWriter) writeHorizontalRule(hr HorizontalRule) {
|
func (w *OrgWriter) writeHorizontalRule(hr HorizontalRule) {
|
||||||
|
|
126
org/table.go
126
org/table.go
|
@ -2,27 +2,35 @@ package org
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Table struct {
|
type Table struct {
|
||||||
Header Node
|
Rows []Row
|
||||||
Rows []Node
|
ColumnInfos []ColumnInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
type TableSeparator struct{ Content string }
|
type Row struct {
|
||||||
|
Columns []Column
|
||||||
type TableHeader struct {
|
IsSpecial bool
|
||||||
SeparatorBefore Node
|
|
||||||
Columns [][]Node
|
|
||||||
SeparatorAfter Node
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type TableRow struct{ Columns [][]Node }
|
type Column struct {
|
||||||
|
Children []Node
|
||||||
|
*ColumnInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type ColumnInfo struct {
|
||||||
|
Align string
|
||||||
|
Len int
|
||||||
|
}
|
||||||
|
|
||||||
var tableSeparatorRegexp = regexp.MustCompile(`^(\s*)(\|[+-|]*)\s*$`)
|
var tableSeparatorRegexp = regexp.MustCompile(`^(\s*)(\|[+-|]*)\s*$`)
|
||||||
var tableRowRegexp = regexp.MustCompile(`^(\s*)(\|.*)`)
|
var tableRowRegexp = regexp.MustCompile(`^(\s*)(\|.*)`)
|
||||||
|
|
||||||
|
var columnAlignRegexp = regexp.MustCompile(`^<(l|c|r)>$`)
|
||||||
|
|
||||||
func lexTable(line string) (token, bool) {
|
func lexTable(line string) (token, bool) {
|
||||||
if m := tableSeparatorRegexp.FindStringSubmatch(line); m != nil {
|
if m := tableSeparatorRegexp.FindStringSubmatch(line); m != nil {
|
||||||
return token{"tableSeparator", len(m[1]), m[2], m}, true
|
return token{"tableSeparator", len(m[1]), m[2], m}, true
|
||||||
|
@ -33,43 +41,87 @@ func lexTable(line string) (token, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Document) parseTable(i int, parentStop stopFn) (int, Node) {
|
func (d *Document) parseTable(i int, parentStop stopFn) (int, Node) {
|
||||||
rows, start := []Node{}, i
|
rawRows, start := [][]string{}, i
|
||||||
for !parentStop(d, i) && (d.tokens[i].kind == "tableRow" || d.tokens[i].kind == "tableSeparator") {
|
for ; !parentStop(d, i); i++ {
|
||||||
consumed, row := d.parseTableRowOrSeparator(i, parentStop)
|
if t := d.tokens[i]; t.kind == "tableRow" {
|
||||||
i += consumed
|
rawRow := strings.FieldsFunc(d.tokens[i].content, func(r rune) bool { return r == '|' })
|
||||||
rows = append(rows, row)
|
for i := range rawRow {
|
||||||
}
|
rawRow[i] = strings.TrimSpace(rawRow[i])
|
||||||
|
|
||||||
consumed := i - start
|
|
||||||
|
|
||||||
if len(rows) >= 2 {
|
|
||||||
if row, ok := rows[0].(TableRow); ok {
|
|
||||||
if separator, ok := rows[1].(TableSeparator); ok {
|
|
||||||
return consumed, Table{TableHeader{nil, row.Columns, separator}, rows[2:]}
|
|
||||||
}
|
}
|
||||||
|
rawRows = append(rawRows, rawRow)
|
||||||
|
} else if t.kind == "tableSeparator" {
|
||||||
|
rawRows = append(rawRows, nil)
|
||||||
|
} else {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(rows) >= 3 {
|
|
||||||
if separatorBefore, ok := rows[0].(TableSeparator); ok {
|
table := Table{nil, getColumnInfos(rawRows)}
|
||||||
if row, ok := rows[1].(TableRow); ok {
|
for _, rawColumns := range rawRows {
|
||||||
if separatorAfter, ok := rows[2].(TableSeparator); ok {
|
row := Row{nil, isSpecialRow(rawColumns)}
|
||||||
return consumed, Table{TableHeader{separatorBefore, row.Columns, separatorAfter}, rows[3:]}
|
if len(rawColumns) != 0 {
|
||||||
|
for i := range table.ColumnInfos {
|
||||||
|
column := Column{nil, &table.ColumnInfos[i]}
|
||||||
|
if i < len(rawColumns) {
|
||||||
|
column.Children = d.parseInline(rawColumns[i])
|
||||||
}
|
}
|
||||||
|
row.Columns = append(row.Columns, column)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
table.Rows = append(table.Rows, row)
|
||||||
|
}
|
||||||
|
return i - start, table
|
||||||
|
}
|
||||||
|
|
||||||
|
func getColumnInfos(rows [][]string) []ColumnInfo {
|
||||||
|
columnCount := 0
|
||||||
|
for _, columns := range rows {
|
||||||
|
if n := len(columns); n > columnCount {
|
||||||
|
columnCount = n
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed, Table{nil, rows}
|
columnInfos := make([]ColumnInfo, columnCount)
|
||||||
|
for i := 0; i < columnCount; i++ {
|
||||||
|
countNumeric, countNonNumeric := 0, 0
|
||||||
|
for _, columns := range rows {
|
||||||
|
if !(i < len(columns)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(columns[i]) > columnInfos[i].Len {
|
||||||
|
columnInfos[i].Len = len(columns[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
if m := columnAlignRegexp.FindStringSubmatch(columns[i]); m != nil && isSpecialRow(columns) {
|
||||||
|
switch m[1] {
|
||||||
|
case "l":
|
||||||
|
columnInfos[i].Align = "left"
|
||||||
|
case "c":
|
||||||
|
columnInfos[i].Align = "center"
|
||||||
|
case "r":
|
||||||
|
columnInfos[i].Align = "right"
|
||||||
|
}
|
||||||
|
} else if _, err := strconv.ParseFloat(columns[i], 32); err == nil {
|
||||||
|
countNumeric++
|
||||||
|
} else if strings.TrimSpace(columns[i]) != "" {
|
||||||
|
countNonNumeric++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if columnInfos[i].Align == "" && countNumeric >= countNonNumeric {
|
||||||
|
columnInfos[i].Align = "right"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return columnInfos
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Document) parseTableRowOrSeparator(i int, _ stopFn) (int, Node) {
|
func isSpecialRow(rawColumns []string) bool {
|
||||||
if d.tokens[i].kind == "tableSeparator" {
|
isAlignRow := true
|
||||||
return 1, TableSeparator{d.tokens[i].content}
|
for _, rawColumn := range rawColumns {
|
||||||
|
if !columnAlignRegexp.MatchString(rawColumn) && rawColumn != "" {
|
||||||
|
isAlignRow = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fields := strings.FieldsFunc(d.tokens[i].content, func(r rune) bool { return r == '|' })
|
return isAlignRow
|
||||||
row := TableRow{}
|
|
||||||
for _, field := range fields {
|
|
||||||
row.Columns = append(row.Columns, d.parseInline(strings.TrimSpace(field)))
|
|
||||||
}
|
|
||||||
return 1, row
|
|
||||||
}
|
}
|
||||||
|
|
9
org/testdata/footnotes.html
vendored
9
org/testdata/footnotes.html
vendored
|
@ -53,13 +53,16 @@ and tables
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>1</td><td>a</td>
|
<td class="align-right">1</td>
|
||||||
|
<td>a</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>2</td><td>b</td>
|
<td class="align-right">2</td>
|
||||||
|
<td>b</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>3</td><td>c</td>
|
<td class="align-right">3</td>
|
||||||
|
<td>c</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
10
org/testdata/lists.html
vendored
10
org/testdata/lists.html
vendored
|
@ -60,11 +60,17 @@ and another one with a table
|
||||||
</p>
|
</p>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<th>a</th><th>b</th><th>c</th>
|
<tr>
|
||||||
|
<th class="align-right">a</th>
|
||||||
|
<th class="align-right">b</th>
|
||||||
|
<th class="align-right">c</th>
|
||||||
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>1</td><td>2</td><td>3</td>
|
<td class="align-right">1</td>
|
||||||
|
<td class="align-right">2</td>
|
||||||
|
<td class="align-right">3</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
6
org/testdata/misc.html
vendored
6
org/testdata/misc.html
vendored
|
@ -20,10 +20,12 @@ crazy ain't it?
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>foo</strong></td><td>foo</td>
|
<td><strong>foo</strong></td>
|
||||||
|
<td>foo</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>bar</strong></td><td>bar</td>
|
<td><strong>bar</strong></td>
|
||||||
|
<td>bar</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
76
org/testdata/tables.html
vendored
76
org/testdata/tables.html
vendored
|
@ -1,11 +1,17 @@
|
||||||
<figure>
|
<figure>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<th>a</th><th>b</th><th>c</th>
|
<tr>
|
||||||
|
<th class="align-right">a</th>
|
||||||
|
<th class="align-right">b</th>
|
||||||
|
<th class="align-right">c</th>
|
||||||
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>1</td><td>2</td><td>3</td>
|
<td class="align-right">1</td>
|
||||||
|
<td class="align-right">2</td>
|
||||||
|
<td class="align-right">3</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -16,11 +22,17 @@ table with separator before and after header
|
||||||
<figure>
|
<figure>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<th>a</th><th>b</th><th>c</th>
|
<tr>
|
||||||
|
<th class="align-right">a</th>
|
||||||
|
<th class="align-right">b</th>
|
||||||
|
<th class="align-right">c</th>
|
||||||
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>1</td><td>2</td><td>3</td>
|
<td class="align-right">1</td>
|
||||||
|
<td class="align-right">2</td>
|
||||||
|
<td class="align-right">3</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -31,9 +43,10 @@ table with separator after header
|
||||||
<figure>
|
<figure>
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr></tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>1</td><td>2</td><td>3</td>
|
<td class="align-right">1</td>
|
||||||
|
<td class="align-right">2</td>
|
||||||
|
<td class="align-right">3</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -45,7 +58,9 @@ table without header (but separator before)
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>1</td><td>2</td><td>3</td>
|
<td class="align-right">1</td>
|
||||||
|
<td class="align-right">2</td>
|
||||||
|
<td class="align-right">3</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -53,3 +68,50 @@ table without header (but separator before)
|
||||||
table without header
|
table without header
|
||||||
</figcaption>
|
</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
|
<figure>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="align-left">left aligned</th>
|
||||||
|
<th class="align-right">right aligned</th>
|
||||||
|
<th class="align-center">center aligned</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="align-left">42</td>
|
||||||
|
<td class="align-right">42</td>
|
||||||
|
<td class="align-center">42</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="align-left">foobar</td>
|
||||||
|
<td class="align-right">foobar</td>
|
||||||
|
<td class="align-center">foobar</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<figcaption>
|
||||||
|
table with aligned columns
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
<figure>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="align-right">long column a</th>
|
||||||
|
<th class="align-right">long column b</th>
|
||||||
|
<th class="align-right">long column c</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="align-right">1</td>
|
||||||
|
<td class="align-right">2</td>
|
||||||
|
<td class="align-right">3</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<figcaption>
|
||||||
|
table with right aligned columns (because numbers)
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
11
org/testdata/tables.org
vendored
11
org/testdata/tables.org
vendored
|
@ -16,3 +16,14 @@
|
||||||
#+CAPTION: table without header
|
#+CAPTION: table without header
|
||||||
| 1 | 2 | 3 |
|
| 1 | 2 | 3 |
|
||||||
|
|
||||||
|
#+CAPTION: table with aligned columns
|
||||||
|
| left aligned | right aligned | center aligned |
|
||||||
|
|--------------+---------------+----------------|
|
||||||
|
| <l> | <r> | <c> |
|
||||||
|
| 42 | 42 | 42 |
|
||||||
|
| foobar | foobar | foobar |
|
||||||
|
|
||||||
|
#+CAPTION: table with right aligned columns (because numbers)
|
||||||
|
| long column a | long column b | long column c |
|
||||||
|
|---------------+---------------+---------------|
|
||||||
|
| 1 | 2 | 3 |
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue