Locations

Addressing cells by what the data says rather than by where they sit.

Keisen’s location functions, the rule that separates a name from a filter, and the style and data-colour directives that take them.

table-style and table-footnote take one location or an array of them.

cells-body(columns: auto, rows: auto), cells-stub(rows: auto), cells-stubhead(), cells-row-groups(groups: auto), cells-column-labels(columns: auto), cells-column-spanners(spanners: auto), cells-title(parts: ("title", "subtitle")), cells-summary(groups: auto, columns: auto, rows: auto), cells-grand-summary(columns: auto, rows: auto), cells-source-notes(notes: auto), cells-footnotes(notes: auto).

A footnote row is numbered by where it lands in the footer, so notes: 0 is the first note printed under the table. The footer prints the marked notes in mark order, then the unmarked ones in the order they were written. Marks are numbered in reading order rather than in the order the table-footnote calls appear, so a note written first but marking a later row prints second, behind the higher mark. A footnote cannot mark a footnote row: which row a note lands on is decided by numbering the marks, so a mark there would have to be numbered before the numbering it takes part in, and it is refused rather than silently ignored.

A summary row answers to the label that names it and to its position within the group, so rows: "Subtotal" and rows: 0 reach the same row. columns: none is the cell carrying the row’s own label, which is how a note goes on the row once rather than on every cell of it.

Names and filters

A selector that spells a name out is held to it, and one that filters is not. A column name, a group label, a spanner label, a summary label, a row index, and a note position are all names, and one the table does not carry is an error rather than a style that quietly reaches nothing. auto and a predicate are filters, and matching nothing is not an error, since a table built from filtered data legitimately has fewer rows on some renderings than on others. This is the rule the row-index case follows in Table parts, and it holds for the format and substitution directives too: format-number("uints") is reported rather than formatting nothing. A column that exists but sits in the stub, or that columns-hide removed, is reported as such rather than as unknown.

An array holds the kind of name the field reads, and nothing else. columns: ("units", 42) is reported rather than aligning units alone, and rows: (0, "2") the same way. A summary row is the one name written either way, as its label or as its position, and both are read.

A location expands against the table into (part, row, column) addresses. This is the part Typst show rules cannot express: they select by element type in document order and never see the row behind a cell.

Styles and colour

style(text: none, fill: none, stroke: none, align: none, inset: none) builds the properties. Only what is set appears, so a later style overrides property by property.

data-colour(palette, columns: auto, rows: auto, domain: auto, target: "fill", missing: none, reverse: false) maps a column onto a palette. The domain spans the rows the directive matches, which is every row by default and is what makes per-group scaling a matter of one data-colour per group. With target: "fill" the text colour is chosen per cell from its background’s relative luminance, so a dark fill never carries unreadable text.

Back to top