More powerful and customizable tables in Typst.
NOTE: This library still has a few bugs, but most of them shouldn't be noticeable. Please open an issue if you find a bug and I'll get to it as soon as I can. (Do not be afraid to open issues!! Also, PRs are welcome!)
To use this library through the Typst package manager (for Typst v0.6.0+), write for example #import "@preview/tablex:0.0.5": tablex, cellx
at the top of your Typst file (you may also add whichever other functions you use from the library to that import list!).
For older Typst versions, download the file tablex.typ
from the latest release (or directly from the main branch, for the 'bleeding edge') at the tablex repository (https://github.com/PgBiel/typst-tablex) and place it on the same folder as your own Typst file. Then, at the top of your file, write for example #import "tablex.typ": tablex, cellx
(plus whichever other functions you use from the library).
This library should be compatible with Typst v0.2.0, v0.3.0, v0.4.0, v0.5.0 and v0.6.0. Using the latest Typst version is recommended (v0.6.0+), as it fixes certain bugs which made it almost impossible to use references and citations from within tablex tables (and also brings the package manager, making using tablex even easier!).
Here's an example of what tablex
can do:
Here's the code for that table:
#import "@preview/tablex:0.0.5": tablex, rowspanx, colspanx
#tablex(
columns: 4,
align: center + horizon,
auto-vlines: false,
// indicate the first two rows are the header
// (in case we need to eventually
// enable repeating the header across pages)
header-rows: 2,
// color the last column's cells
// based on the written number
map-cells: cell => {
if cell.x == 3 and cell.y > 1 {
cell.content = {
let value = int(cell.content.text)
let text-color = if value < 10 {
red.lighten(30%)
} else if value < 15 {
yellow.darken(13%)
} else {
green
}
set text(text-color)
strong(cell.content)
}
}
cell
},
/* --- header --- */
rowspanx(2)[*Username*], colspanx(2)[*Data*], (), rowspanx(2)[*Score*],
(), [*Location*], [*Height*], (),
/* -------------- */
[John], [Second St.], [180 cm], [5],
[Wally], [Third Av.], [160 cm], [10],
[Jason], [Some St.], [150 cm], [15],
[Robert], [123 Av.], [190 cm], [20],
[Other], [Unknown St.], [170 cm], [25],
)
In most cases, you should be able to replace #table
with #tablex
and be good to go for a start - it should look very similar (if not identical). Indeed, the syntax is very similar for the basics:
#import "@preview/tablex:0.0.5": tablex
#tablex(
columns: (auto, 1em, 1fr, 1fr), // 4 columns
rows: auto, // at least 1 row of auto size
fill: red,
align: center + horizon,
stroke: green,
[a], [b], [c], [d],
[e], [f], [g], [h],
[i], [j], [k], [l]
)
There are still a few oddities in the library (see Known Issues for more info), but, for the vast majority of cases, replacing #tablex
by #table
should work just fine. (Sometimes you can even replace #grid
by #gridx
- see the line customization section for more -, but not always, as the behavior is a bit different.)
This is mostly a word of caution in case anything I haven't anticipated happens, but, based on my tests (and after tons of bug-fixing commits), the vast majority of tables (that don't face one of the listed known issues) should work just fine under the library.
Your cells can now span more than one column and/or row at once, with colspanx
/ rowspanx
:
#import "@preview/tablex:0.0.5": tablex, colspanx, rowspanx
#tablex(
columns: 3,
colspanx(2)[a], (), [b],
[c], rowspanx(2)[d], [ed],
[f], (), [g]
)
Note that the empty parentheses there are just for organization, and are ignored (unless they come before the first cell - more on that later). They're useful to help us keep track of which cell positions are being used up by the spans, because, if we try to add an actual cell at these spots, it will just push the others forward, which might seem unexpected.
Use colspanx(2)(rowspanx(2)[d])
to colspan and rowspan at the same time. Be careful not to attempt to overwrite other cells' spans, as you will get a nasty error.
You can now ensure the first row (or, rather, the rows covered by the first rowspan) in your table repeats across pages. Just use repeat-header: true
(default is false
).
Note that you may wish to customize this. Use repeat-header: 6
to repeat for 6 more pages. Use repeat-header: (2, 4)
to repeat only on the 2nd and the 4th page (where the 1st page is the one the table starts in). Additionally, use header-rows: 5
to ensure the first (e.g.) 5 rows are part of the header (by default, this is 1 - more rows will be repeated where necessary if rowspans are used).
Also, note that, by default, the horizontal lines below the header are transported to other pages, which may be an annoyance if you customize lines too much (see below). Use header-hlines-have-priority: false
to ensure that the first row in each page will dictate the appearance of the horizontal lines above it (and not the header).
Note: Please open a GitHub issue if you have any issues with this feature. Note that the table must be contained within pages of same dimensions and (top) margins for this to work properly (or, really, for most things in tablex
to work properly).
Example:
#import "@preview/tablex:0.0.5": tablex, hlinex, vlinex, colspanx, rowspanx
#pagebreak()
#v(80%)
#tablex(
columns: 4,
align: center + horizon,
auto-vlines: false,
repeat-header: true,
/* --- header --- */
rowspanx(2)[*Names*], colspanx(2)[*Properties*], (), rowspanx(2)[*Creators*],
(), [*Type*], [*Size*], (),
/* -------------- */
[Machine], [Steel], [5 $"cm"^3$], [John p& Kate],
[Frog], [Animal], [6 $"cm"^3$], [Robert],
[Frog], [Animal], [6 $"cm"^3$], [Robert],
[Frog], [Animal], [6 $"cm"^3$], [Robert],
[Frog], [Animal], [6 $"cm"^3$], [Robert],
[Frog], [Animal], [6 $"cm"^3$], [Robert],
[Frog], [Animal], [6 $"cm"^3$], [Robert],
[Frog], [Animal], [6 $"cm"^3$], [Rodbert],
)
Every single line in the table is either a hlinex
(horizontal) or vlinex
(vertical) instance. By default, there is one between every column and between every row - unless you specify a custom line for some column or row, in which case the automatic line for it will be removed (to allow you to freely customize it). To disable this behavior, use auto-lines: false
, which will remove all automatic lines. You may also remove only automatic horizontal lines with auto-hlines: false
, and only vertical with auto-vlines: false
.
Note: gridx
is an alias for tablex
with auto-lines: false
.
For your custom lines, write hlinex()
at any position and it will add a horizontal line below the current cell row (or at the top, if before any cell). You can use hlinex(start: a, end: b)
to control the cells which that line spans (a
is the first column number and b
is the last column number). You can also specify its stroke (color/thickness) with hlinex(stroke: red + 5pt)
for example. To position it at an arbitrary row, use hlinex(y: 6)
or similar. (Columns and rows are indexed starting from 0.)
Something similar occurs for vlinex()
, which has start
, end
(first row and last row it spans), and also stroke
. They will, by default, be placed to the right of the current cell, and will span the entire table (top to bottom). To override the default placement, use vlinex(x: 2)
or similar.
Note: Only one hline or vline with the same span (same start/end) can be placed at once.
Note: You can also place vlines before the first cell, in which case they will be placed consecutively, each after the last vlinex()
. That is, if you place several of them in a row (before the first cell only), then it will not place all of them at one location (which is normally what happens if you try to place multiple vlines at once), but rather one after the other. With this behavior, you can also specify ()
between each vline to skip certain positions (again, only before the first cell - afterwards, all ()
are ignored). Note that you can also just ignore this entirely and use vlinex(x: 0)
, vlinex(x: 1)
, ..., vlinex(x: columns.len())
for full control.
Here's some sample usage:
#import "@preview/tablex:0.0.5": tablex, gridx, hlinex, vlinex, colspanx, rowspanx
#tablex(
columns: 4,
auto-lines: false,
// skip a column here vv
vlinex(), vlinex(), vlinex(), (), vlinex(),
colspanx(2)[a], (), [b], [J],
[c], rowspanx(2)[d], [e], [K],
[f], (), [g], [L],
// ^^ '()' after the first cell are 100% ignored
)
#tablex(
columns: 4,
auto-vlines: false,
colspanx(2)[a], (), [b], [J],
[c], rowspanx(2)[d], [e], [K],
[f], (), [g], [L],
)
#gridx(
columns: 4,
(), (), vlinex(end: 2),
hlinex(stroke: yellow + 2pt),
colspanx(2)[a], (), [b], [J],
hlinex(start: 0, end: 1, stroke: yellow + 2pt),
hlinex(start: 1, end: 2, stroke: green + 2pt),
hlinex(start: 2, end: 3, stroke: red + 2pt),
hlinex(start: 3, end: 4, stroke: blue.lighten(50%) + 2pt),
[c], rowspanx(2)[d], [e], [K],
hlinex(start: 2),
[f], (), [g], [L],
)
You can also bulk-customize lines by specifying map-hlines: h => new_hline
and map-vlines: v => new_vline
. This includes any automatically generated lines. For example:
#import "@preview/tablex:0.0.5": tablex, colspanx, rowspanx
#tablex(
columns: 3,
map-hlines: h => (..h, stroke: blue),
map-vlines: v => (..v, stroke: green + 2pt),
colspanx(2)[a], (), [b],
[c], rowspanx(2)[d], [ed],
[f], (), [g]
)
Cells can be customized entirely. Instead of specifying content (e.g. [text]
) as a table item, you can specify cellx(property: a, property: b, ...)[text]
, which allows you to customize properties, such as:
colspan: 2
(same as usingcolspanx(2, ...)[...]
)rowspan: 3
(same as usingrowspanx(3, ...)[...]
)align: center
(override whole-table alignment for this cell)fill: blue
(fill just this cell with that color)inset: 0pt
(override inset/internal padding for this cell - note that this can look off unless you use auto columns and rows)x: 5
(arbitrarily place the cell at the given column, beginning at 0 - may error if conflicts occur)y: 6
(arbitrarily place the cell at the given row, beginning at 0 - may error if conflicts occur)
Additionally, instead of specifying content to the cell, you can specify a function (column, row) => content
, allowing each cell to be aware of where it's positioned. (Note that positions are recorded in the cell's .x
and .y
attributes, and start as auto
unless you specify otherwise.)
For example:
#import "@preview/tablex:0.0.5": tablex, cellx, colspanx, rowspanx
#tablex(
columns: 3,
fill: red,
align: right,
colspanx(2)[a], (), [beeee],
[c], rowspanx(2)[d], cellx(fill: blue, align: left)[e],
[f], (), [g],
// place this cell at the first column, seventh row
cellx(colspan: 3, align: center, x: 0, y: 6)[hi I'm down here]
)
To customize multiple cells at once, you have a few options:
-
map-cells: cell => cell
(given a cell, returns a new cell). You can use this to customize the cell's attributes, but also to change its positions (however, avoid doing that as it can easily generate conflicts). You can access the cell's position withcell.x
andcell.y
. All other attributes are also accessible and changeable (see theReference
further below for a list). Return something like(..cell, fill: blue)
, for example, to ensure the other properties (including the cell type marker) are kept. (Callingcellx
here is not necessary. If overriding the cell's content, usecontent: [whatever]
). This is useful if you want to, for example, customize a cell's fill color based on its contents, or add some content to every cell, or something similar. -
map-rows: (row_index, cells) => cells
(given a row index and all cells in it, return a new array of cells). Allows customizing entire rows, but note that the cells in thecells
parameter can benone
if they're some position occupied by a colspan or rowspan of another cell. Ensure you return the cells in the order you were given, including thenone
s, for best results. Also, you cannot move cells here to another row. You can change the cells' columns (by changing theirx
property), but that will certainly generate conflicts if any col/rowspans are involved (in general, you cannot bulk-change col/rowspans withoutmap-cells
). -
map-cols: (col_index, cells) => cells
(given a column index and all cells in it, return a new array of cells). Similar tomap-rows
, but for customizing columns. You cannot change the column of any cell here. (To do that,map-cells
is required.) You can, however, change its row (withy
, but do that sparingly), and, of course, all other properties.
Note: Execution order is map-cells
=> map-rows
=> map-cols
.
Example:
#import "@preview/tablex:0.0.5": tablex, colspanx, rowspanx
#tablex(
columns: 4,
auto-vlines: true,
// make all cells italicized
map-cells: cell => {
(..cell, content: emph(cell.content))
},
// add some arbitrary content to entire rows
map-rows: (row, cells) => cells.map(c =>
if c == none {
c // keeping 'none' is important
} else {
(..c, content: [#c.content\ *R#row*])
}
),
// color cells based on their columns
// (using 'fill: (column, row) => color' also works
// for this particular purpose)
map-cols: (col, cells) => cells.map(c =>
if c == none {
c
} else {
(..c, fill: if col < 2 { blue } else { yellow })
}
),
colspanx(2)[a], (), [b], [J],
[c], rowspanx(2)[dd], [e], [K],
[f], (), [g], [L],
)
Another example (summing columns):
#gridx(
columns: 3,
rows: 6,
fill: (col, row) => (blue, red, green).at(calc.mod(row + col - 1, 3)),
map-cols: (col, cells) => {
let last = cells.last()
last.content = [
#cells.slice(0, cells.len() - 1).fold(0, (acc, c) => if c != none { acc + eval(c.content.text) } else { acc })
]
last.fill = aqua
cells.last() = last
cells
},
[0], [5], [10],
[1], [6], [11],
[2], [7], [12],
[3], [8], [13],
[4], [9], [14],
[s], [s], [s]
)
-
Filled cells will partially overlap with horizontal lines above them (see PgBiel#4).
- To be fixed in a future rework of the table drawing process.
-
Table lines don't play very well with column and row gutter when a colspan or rowspan is used. They may be missing or be cut off by gutters.
-
Rows with fractional height (such as
2fr
) have zero height if the table spans more than one page. This is because fractional row heights are calculated on the available height of the first page of the table, which is something that the default#table
can circumvent using internal code. This won't be fixed for now. (Columns with fractional width work fine, provided all pages the table is in have the same width, and the page width isn'tauto
(which forces fractional columns to be 0pt, even in the default#table
).) -
By default, the table assumes that all pages containing it have the same width and height (dimensions). This is used for auto-sizing of columns/rows and for repeatable headers to work properly. It would be potentially costly to re-calculate page sizes on every page, so this was postponed.
-
tablex
can potentially be slower and/or take longer to compile than the defaulttable
(especially when the table spans a lot of pages). Please use the latest Typst version to reduce this problem (each version has been bringing further improvements in this sense). Still, we are looking for ways to better optimize the library (see more discussion at PgBiel#5 - feel free to give some input!). However, re-compilation is usually fine thanks to Typst's built-in memoization. -
The internals of the library still aren't very well documented; I plan on adding more info about this eventually.
-
Please open a GitHub issue for anything weird you come across (make sure others haven't reported it first).
-
cellx
: Represents a table cell, and is initialized as follows:#let cellx(content, x: auto, y: auto, rowspan: 1, colspan: 1, fill: auto, align: auto, inset: auto ) = ( tablex-dict-type: "cell", content: content, rowspan: rowspan, colspan: colspan, align: align, fill: fill, inset: inset, x: x, y: y, )
where:
tablex-dict-type
is the type markercontent
is the cell's content (eithercontent
or a function with(col, row) => content
)rowspan
is how many rows this cell spans (default 1)colspan
is how many columns this cell spans (default 1)align
is this cell's align override, such as "center" (defaultauto
to follow the rest of the table)fill
is this cell's fill override, such as "blue" (defaultauto
to follow the rest of the table)inset
is this cell's inset override, such as5pt
(defaultauto
to follow the rest of the table)x
is the cell's column index (0..len-1) -auto
indicates it wasn't assigned yety
is the cell's row index (0..len-1) -auto
indicates it wasn't assigned yet
-
hlinex
: represents a horizontal line:#let hlinex( start: 0, end: auto, y: auto, stroke: auto, stop-pre-gutter: auto, gutter-restrict: none, stroke-expand: true, expand: none ) = ( tablex-dict-type: "hline", start: start, end: end, y: y, stroke: stroke, stop-pre-gutter: stop-pre-gutter, gutter-restrict: gutter-restrict, stroke-expand: stroke-expand, expand: expand, parent: none, )
where:
tablex-dict-type
is the type markerstart
is the column index where the hline starts from (default0
, a.k.a. the beginning)end
is the last column the hline touches (defaultauto
, a.k.a. all the way to the end)- Note that hlines will not be drawn over cells with
colspan
larger than 1, even if their spans (start
-end
) include that cell.
- Note that hlines will not be drawn over cells with
y
is the index of the row at the top of which the hline is drawn. (Defaults toauto
, a.k.a. depends on where you placed thehline
among the table items - it's always on the top of the row below the current one.)stroke
is the hline's stroke override (defaults toauto
, a.k.a. follow the rest of the table).stop-pre-gutter
: Whentrue
, the hline will not be drawn over gutter (which is the default behavior of tables). Defaults toauto
which is essentiallyfalse
(draw over gutter).gutter-restrict
: Eithertop
,bottom
, ornone
. Has no effect ifrow-gutter
is set tonone
. Otherwise, defines if thishline
should be drawn only on the top of the row gutter (top
); on the bottom (bottom
); or on both the top and the bottom (none
, the default). Note thattop
andbottom
are alignment values (not strings).stroke-expand
: Whentrue
, the hline will be extended as necessary to cover the stroke of the vlines going through either end of the line. Defaults totrue
.expand
: Optionally extend the hline by an arbitrary length. Whennone
, it is not expanded. When a length (such as5pt
), it is expanded by that length on both ends. When an array of two lengths (such as(5pt, 10pt)
), it is expanded to the left by the first length (in this case,5pt
) and to the right by the second (in this case,10pt
). Defaults tonone
.parent
: An internal attribute determined when splitting lines among cells. (It should always benone
on user-facing interfaces.)
-
vlinex
: represents a vertical line:#let vlinex( start: 0, end: auto, x: auto, stroke: auto, stop-pre-gutter: auto, gutter-restrict: none, stroke-expand: true, expand: none ) = ( tablex-dict-type: "vline", start: start, end: end, x: x, stroke: stroke, stop-pre-gutter: stop-pre-gutter, gutter-restrict: gutter-restrict, stroke-expand: stroke-expand, expand: expand, parent: none, )
where:
tablex-dict-type
is the type markerstart
is the row index where the vline starts from (default0
, a.k.a. the top)end
is the last row the vline touches (defaultauto
, a.k.a. all the way to the bottom)- Note that vlines will not be drawn over cells with
rowspan
larger than 1, even if their spans (start
-end
) include that cell.
- Note that vlines will not be drawn over cells with
x
is the index of the column to the left of which the vline is drawn. (Defaults toauto
, a.k.a. depends on where you placed thevline
among the table items.)- For a
vline
to be placed after all columns, itsx
value will be equal to the amount of columns (which isn't a valid column index, but it's what is used here).
- For a
stroke
is the vline's stroke override (defaults toauto
, a.k.a. follow the rest of the table).stop-pre-gutter
: Whentrue
, the vline will not be drawn over gutter (which is the default behavior of tables). Defaults toauto
which is essentiallyfalse
(draw over gutter).gutter-restrict
: Eitherleft
,right
, ornone
. Has no effect ifcolumn-gutter
is set tonone
. Otherwise, defines if thisvline
should be drawn only to the left of the column gutter (left
); to the right (right
); or on both the left and the right (none
, the default). Note thatleft
andright
are alignment values (not strings).stroke-expand
: Whentrue
, the vline will be extended as necessary to cover the stroke of the hlines going through either end of the line. Defaults totrue
.expand
: Optionally extend the vline by an arbitrary length. Whennone
, it is not expanded. When a length (such as5pt
), it is expanded by that length on both ends. When an array of two lengths (such as(5pt, 10pt)
), it is expanded towards the top by the first length (in this case,5pt
) and towards the bottom by the second (in this case,10pt
). Defaults tonone
.parent
: An internal attribute determined when splitting lines among cells. (It should always benone
on user-facing interfaces.)
-
The
occupied
type is an internal type used to represent cell positions occupied by cells withcolspan
orrowspan
greater than 1. -
Use
is-tablex-cell
,is-tablex-hline
,is-tablex-vline
andis-tablex-occupied
to check if a particular object has the corresponding type marker. -
colspanx
androwspanx
are shorthands for setting thecolspan
androwspan
attributes ofcellx
. They can also be nested (one given as an argument to the other) to combine their properties (e.g.,colspanx(2)(rowspanx(3)[a])
). They accept all other cell properties with named arguments. For example,colspanx(2, align: center)[b]
is equivalent tocellx(colspan: 2, align: center)[b]
.
-
gridx
is equivalent totablex
withauto-lines: false
; see below. -
tablex:
The main function for creating a table with this library:#let tablex( columns: auto, rows: auto, inset: 5pt, align: auto, fill: none, stroke: auto, column-gutter: auto, row-gutter: auto, gutter: none, repeat-header: false, header-rows: 1, header-hlines-have-priority: true, auto-lines: true, auto-hlines: auto, auto-vlines: auto, map-cells: none, map-hlines: none, map-vlines: none, map-rows: none, map-cols: none, ..items ) = { // ... }
Parameters:
-
columns
: The sizes of each column. They work just like regulartable
's columns, and can be:- an array of lengths (
1pt
,2em
,100%
, ...), including fractional (2fr
), to specify the width of each columnauto
may be specified to automatically resize the column based on the space available- when specifying fractional columns, the available space is divided between them, weighted on the fraction value of each column
- For example, with
(1fr, 2fr)
, the available space will be divided by 3 (1 + 2), and the first column will have 1/3 of the space, while the second will have 2/3.
- For example, with
- a single length like above, to indicate the width of a single column (equivalent to just placing it inside a unit array)
- an integer (such as
4
), as a shorthand for(auto,) * 4
(that manyauto
columns)
- an array of lengths (
-
rows
: The sizes of each row. They follow the exact same format ascolumns
, except that the "available space" is infinite (auto rows can expand as much as is needed, as the table can add rows over multiple pages).- Note: If more rows than specified are added, the height for the last row will be the one assigned to all extra rows. (If the last row is
auto
, the extra ones will also beauto
, for example.) - Warning: support for fractional sizes for rows is still rudimentary - they only work properly on the table's first page; on the second page and onwards, they will not behave properly, differently from the default
#table
.
- Note: If more rows than specified are added, the height for the last row will be the one assigned to all extra rows. (If the last row is
-
inset
: Inset/internal padding to give to each cell. Defaults to5pt
(the#table
default). -
align
: How to align text in the cells. Defaults toauto
, which inherits alignment from the outer context. Must be eitherauto
, analignment
(such asleft
ortop
), a2d alignment
(such asleft + top
), anarray
of alignment/2d alignment (one for each column in the table - if there are more columns than alignment values, they will alternate); or a function(column, row) => alignment/2d alignment
(to customize for each individual cell). -
fill
: Color with which to fill cells' backgrounds. Defaults tonone
, or no fill. Must be either acolor
, such asblue
; anarray
of colors (one for each column in the table - if there are more columns than colors, they will alternate); or a function(column, row) => color
(to customize for each individual cell). -
stroke
: Indicates how to draw the table lines. Defaults to the current line styles in the document. For example:5pt + red
to change the color and the thickness. -
column-gutter
: optional separation (length) between columns (such as5pt
). Defaults tonone
(disable). At the moment, looks a bit ugly if your table has ahline
attempting to cross acolspan
. -
row-gutter
: optional separation (length) between rows. Defaults tonone
(disable). At the moment, looks a bit ugly if your table has avline
attempting to cross arowspan
. -
gutter
: Sets a length to bothcolumn-
androw-gutter
at the same time (overridable by each). -
repeat-header
: Controls header repetition. If set totrue
, the first row (or the amount of rows specified inheader-rows
), including its rowspans, is repeated across all pages this table spans. If set tofalse
(default), the aforementioned header row is not repeated in any page. If set to an integer (such as4
), repeats for that many pages after the first, then stops. If set to an array of integers (such as(3, 4)
), repeats only on those pages relative to the table's first page (page 1 here is where the table is, so adding1
to said array has no effect). -
header-rows
: minimum amount of rows for the repeatable header. 1 by default. Automatically increases if one of the cells is a rowspan that would go beyond the given amount of rows. For example, if 3 is given, then at least the first 3 rows will repeat. -
header-hlines-have-priority
: iftrue
, the horizontal lines below the header being repeated take priority over the rows they appear atop of on further pages. Iffalse
, they draw their own horizontal lines. Defaults totrue
.- For example, if your header has a blue hline under it, that blue hline will display on all pages it is repeated on if this option is
true
. If this option isfalse
, the header will repeat, but the blue hline will not.
- For example, if your header has a blue hline under it, that blue hline will display on all pages it is repeated on if this option is
-
auto-lines
: Shorthand to apply a boolean to bothauto-hlines
andauto-vlines
at the same time (overridable by each). Defaults totrue
. -
auto-hlines
: Iftrue
, draw a horizontal line on every line where you did not manually draw one; iffalse
, no hlines other than the ones you specify (viahlinex
) are drawn. Defaults toauto
(followsauto-lines
, which in turn defaults totrue
). -
auto-vlines
: Iftrue
, draw a vertical line on every line where you did not manually draw one; iffalse
, no vlines other than the ones you specify (viavlinex
) are drawn. Defaults toauto
(followsauto-lines
, which in turn defaults totrue
). -
map-cells
: A function which takes a singlecellx
and returns anothercellx
, or acontent
which is converted tocellx
bycellx[#content]
. You can customize the cell in pretty much any way using this function; just take care to avoid conflicting with already-placed cells if you move it. -
map-hlines
: A function which takes each horizontal line object (hlinex
) and returns another, optionally modifying its properties. You may also change its row position (y
). Note that this is also applied to lines generated byauto-hlines
. -
map-vlines
: A function which takes each horizontal line object (vlinex
) and returns another, optionally modifying its properties. You may also change its column position (x
). Note that this is also applied to lines generated byauto-vlines
. -
map-rows
: A function mapping each row of cells to new values or modified properties. Takes(row_num, cell_array)
and returns the modifiedcell_array
. Note that, with your function, they cannot be sent to another row. Also, please preserve the order of the cells. This is especially important given that cells may benone
if they're actually a position taken by another cell with colspan/rowspan. Make sure thenone
values are in the same indexes when the array is returned. -
map-cols
: A function mapping each column of cells to new values or modified properties. Takes(col_num, cell_array)
and returns the modifiedcell_array
. Note that, with your function, they cannot be sent to another column. Also, please preserve the order of the cells. This is especially important given that cells may benone
if they're actually a position taken by another cell with colspan/rowspan. Make sure thenone
values are in the same indexes when the array is returned.
-
โ ๏ธ Minimum Typst version raised to v0.2.0- Improved calculation of page/container dimensions by using the
layout()
function.- Fixes tables with fractional columns not displaying properly in blocks with
auto
width (PgBiel#44; PgBiel#39) - Fixes some nested tables overflowing the page width (PgBiel#41)
- Fixes bad interaction between tables with fractional columns and nested tables (PgBiel#28)
- Fixes table rotation messing up table size calculation (PgBiel#52)
- Probably fixes other issues not listed here as well.
- Fixes tables with fractional columns not displaying properly in blocks with
- Added some guards for infinite lengths and
auto
-sized pages (PgBiel#47). - Fixed tablex crashes/improper behavior with
em
strokes and other types of strokes (PgBiel#49). - Added the tablex version number as a comment in the source file (as requested in PgBiel#25).
- Added
typst.toml
to support Typst v0.6.0's soon-to-be-released package manager (see PgBiel#22). - Fixed a division by zero regression from v0.0.3 (PgBiel#19).
- Fixed a bug where cells placed in arbitrary positions could force an extra empty row to appear (PgBiel#16).
- Fixed
hlinex(gutter-restrict: top)
causing the hline to just disappear (PgBiel#20). - Fixed certain
gutter-restrict
lines disappearing when there's no gutter (PgBiel#21). - Fixed row gutter lines not properly splitting across pages (PgBiel#23).
- Added support for Typst v0.4.0 and v0.5.0.
- The tablex options
fill:
andalign:
now accept arrays of values for each column (PgBiel#13).- For example,
fill: (red, blue)
would fill the first column with red, the second column with blue, and any further columns would alternate between the two fill colors.
- For example,
- The tablex options
- Fixed the calculation of the size of
auto
rows and columns when a rowspan or colspan was used (PgBiel#11). - Fixed the calculation of the size of the last
auto
column when it was too long (PgBiel#6).
- Added support for Typst v0.3.0.
- Fixed strokes - now lines will expand to not look weird when strokes are larger.
- You can disable this behavior by setting
stroke-expand: false
on your lines.
- You can disable this behavior by setting
- You can now arbitrarily change your lines' sizes at either end with the option
expand: (length, length)
; e.g.expand: (5pt, 10pt)
will increase your horizontal line 5pt to the left and 10pt to the right (or, for a vertical line, 5pt to the top and 10pt to the bottom).- Support for negative expand lengths is limited (so far, only reduces length in the first cell the line spans).
- Added some gutter fixes (not all gutter issues were fixed yet).
Initial release.
- Added types
tablex
,cellx
,hlinex
,vlinex
- Added type aliases
gridx
,rowspanx
,colspanx
- General
- More docs
- Code cleanup
- Table drawing rework
-
#table
parity-
columns:
,rows:
- Basic support
- Accept a single size to mean a single column
- Adjust
auto
columns and rows - Accept integers to mean multiple
auto
- Basic unit conversion (em -> pt, etc.)
- Ratio unit conversion (100% -> page width...)
- Fractional unit conversion based on available space (1fr, 2fr -> 1/3, 2/3)
- Shrink
auto
columns based on available space
-
fill
- Basic support (
color
for general fill) - Accept a function (
(column, row) => color
) - Accept an array of colors (one for each column)
- Basic support (
-
align
- Basic support (
alignment
and2d alignment
apply to all cells) - Accept a function (
(column, row) => alignment/2d alignment
) - Accept an array of alignment values (one for each column)
- Basic support (
-
inset
-
gutter
- Basic support
-
column-gutter
-
row-gutter
-
- Hline, vline adaptations
-
stop-pre-gutter
: Makes the hline/vline not transpose gutter boundaries -
gutter-restrict
: Makes the hline/vline not draw on both sides of a gutter boundary, and instead pick one (top/bottom; left/right) - Properly work with gutters after colspanxs/rowspanxs
-
- Basic support
-
stroke
- Basic support (change all lines, vline or hline, without override)
-
none
for no stroke
- Default to lines on every row and column
-
- New features for
#tablex
- Basic types (
cellx
,hlinex
,vlinex
) -
hlinex
,vlinex
- Auto-positioning when placed among cells
- Arbitrary positioning
- Allow customizing
stroke
-
colspanx
,rowspanx
- Interrupt
hlinex
andvlinex
withend: auto
- Support simultaneous col/rowspan with
cellx(colspanx:, rowspanx:)
- Support nesting colspan/rowspan (
colspanx(rowspanx())
) - Support cell attributes (e.g.
colspanx(2, align: left)[a]
) - Reliably detect conflicts
- Interrupt
- Repeating headers
- Basic support (first row group repeats on every page)
- Work with different page sizes
-
repeat-header
: Control header repetition-
true
: Repeat on all pages - integer: Repeat for the next 'n' pages
- array of integers: Repeat on those (relative) pages
-
false
(default): Do not repeat
-
-
header-rows
: Indicate what to consider as a "header"- integer: At least first 'n' rows are a header (plus whatever rowspanxs show up there)
- Defaults to 1
-
none
or0
: no header (disables header repetition regardless ofrepeat-header
)
- integer: At least first 'n' rows are a header (plus whatever rowspanxs show up there)
-
cellx
- Auto-positioning based on order and columns
- Place empty cells when there are too many
- Allow arbitrary positioning with
cellx(x:, y:)
- Allow
align
override - Allow
fill
override - Allow
inset
override- Works properly only with
auto
cols/rows
- Works properly only with
- Dynamic content (maybe shortcut for
map-cells
on a single cell)
- Auto-lines
-
auto-hlines
-true
to place on all lines without hlines,false
otherwise -
auto-vlines
- similar -
auto-lines
- controls both simultaneously (defaults totrue
)
-
- Iteration attributes
-
map-cells
- Customize every single cell -
map-hlines
- Customize each horizontal line -
map-vlines
- Customize each vertical line -
map-rows
- Customize entire rows of cells -
map-cols
- Customize entire columns of cells
-
- Basic types (
MIT license (see the LICENSE
file).