Wit

Tables

A Wit table is one node. Hand it rows and it draws a full <table> — caption, header, body — with no grid of pipes to align. Rows can be typed in place, come from a list of records, or be written as row / col child nodes when cells need links and emphasis.

Which form?

Pick a form
You haveUseHeader comes from
short rows typed by handrows in placethe first row
a list of recordsrows: @namethe first record's keys
a list of records and your own labelsschema plus rowsthe schema
cells with links or emphasisrow and col nodesthe first row

Rows in place

Pass a list of rows in the rows parameter, one row per line in square brackets. The first row is the header. A caption rides above the table.

source
@table(caption: Output formats, rows: [
  [Format, Extension]
  [Web page, .html]
  [Markdown, .md]
  [Print, .pdf]
])
result
Output formats
FormatExtension
Web page.html
Markdown.md
Print.pdf

Emits:

<table><caption>Output formats</caption><thead><tr><th>Format</th><th>Extension</th></tr></thead><tbody><tr><td>Web page</td><td>.html</td></tr><tr><td>Markdown</td><td>.md</td></tr><tr><td>Print</td><td>.pdf</td></tr></tbody></table>

Short tables fit on one line: @table(rows: [[Client, Hours], [Couple, 0.75]]). Numbers keep the form you wrote, so 1.50 stays 1.50.

Drop the header with header: false — the first row becomes a plain body row:

source
@table(header: false, rows: [[Web page, .html], [Markdown, .md]])
result
Web page.html
Markdown.md
<table><tbody><tr><td>Web page</td><td>.html</td></tr><tr><td>Markdown</td><td>.md</td></tr></tbody></table>

From a list of records

Point rows at a list of records and each record becomes a row. With no schema, the columns are the first record's keys.

source
#refs: [
  { author: Weil, S., year: 1952 }
  { author: Berger, J., year: 1972 }
] !!

@table(rows: @refs)
result
authoryear
Weil, S.1952
Berger, J.1972
<table><thead><tr><th>author</th><th>year</th></tr></thead><tbody><tr><td>Weil, S.</td><td>1952</td></tr><tr><td>Berger, J.</td><td>1972</td></tr></tbody></table>

The commas inside Weil, S. are safe: a record value runs until the next key:.

Pick and label the columns

A schema chooses the columns. As a list, it picks fields in order and uses the field names as headings. As a record, each key picks a field and its value is the heading:

source
#sites: [
  { name: Dunmore Head, status: operational, keeper: A. Vane }
  { name: Carrick Point, status: maintenance, keeper: R. Moss }
] !!

@table(schema: [name, status], rows: @sites)

@table(schema: { name: Site, status: Status }, rows: @sites)
result
namestatus
Dunmore Headoperational
Carrick Pointmaintenance
SiteStatus
Dunmore Headoperational
Carrick Pointmaintenance

The first table has headings name / status; the second Site / Status. Both leave out keeper. Loading the records from a file at build time works the same way; see Data.

Rich cells: row and col nodes

When cells need links, emphasis, or other nodes, leave off rows and write the table's body: a row per row, a col per cell.

source
@table(caption: Modules)
(row (col Module col) (col Notes col) row)
(row (col Parser col) (col Reads *source*; see (a(href: /docs/reference/syntax/) the syntax a). col) row)
table@
result
Modules
ModuleNotes
ParserReads source; see the syntax.
<table><caption>Modules</caption><thead><tr><th>Module</th><th>Notes</th></tr></thead><tbody><tr><td>Parser</td><td>Reads <strong>source</strong>; see <a href="/docs/reference/syntax/">the syntax</a>.</td></tr></tbody></table>

The first row is the header unless you pass header: false. A th cell is always a header cell, even in a body row. The HTML names tr / td / th work too.

Rows from data, with rich cells

Wrap the row in (each … as …) to make one row per record. Fields work in cell text and in parameters such as a link's href. Add an (if …) to filter:

source
#modules: [
  { name: Parser, status: stable, page: /docs/build/parsing-ast/ }
  { name: Sandbox, status: draft, page: /docs/build/scripting/ }
] !!

@table(caption: Stable modules)
(row (col Module col) (col Status col) row)
(each @modules as m)
(if @m.status is stable)
(row (col (a(href: @m.page) @m.name a) col) (col (em @m.status em) col) row)
(end)
(end)
table@
result
Stable modules
ModuleStatus
Parserstable

The draft row drops out:

<table><caption>Stable modules</caption><thead><tr><th>Module</th><th>Status</th></tr></thead><tbody><tr><td><a href="/docs/build/parsing-ast/">Parser</a></td><td><em>stable</em></td></tr></tbody></table>

Header and caption controls

Header controls
ParameterEffect
caption: textadds a caption element
header: falseno header row
header: Nrow N (from 0) becomes the header
header: a list of labelsexplicit header cells; every row is data
(none)the first row is the header

Edge cases

Edge cases
CaseBehaviour
empty or missing rowsan empty table element
null cellan empty cell
number or boolean cellits written form
comma in a row typed in placestarts a new cell

Centring is theme, not renderer

The default theme centres tables. --raw ships a reset-only base, so tables there are not centred — add your own CSS.

See also