This is turning into a hacking bonanza. I guess we’ll just keep trying until something works.
Combining the previous wide row from this thread and with Andrew’s non expanding cell: How to avoid that a large table footer widens the whole table? - #8 by Andrew
Then we could potentially measure all the table column widths:
code
#set page(margin: 1cm)
#let make-label(counter, alignment, n: auto) = {
assert(alignment in (left, right))
let counter-name = repr(counter).split("\"").at(1)
let alignment-str = repr(alignment)
let n = if n == auto { str(counter.get().first()) } else { str(n) }
label(counter-name + "." + n + "." + alignment-str)
}
#let cell-counter = counter("cell-counter")
#let table-counter = counter("table-counter")
#let pin-corner(counter, alignment) = context {
place(alignment)[#metadata(none)#make-label(counter, alignment)]
}
#let pin-left-right(counter) = {
pin-corner(counter, left)
pin-corner(counter, right)
}
#let mark-cell(counter, body, ..args) = table.cell(
..args,
counter.step() + pin-left-right(counter) + body,
)
#let get-pinned-delta-x(counter) = {
let cell-inset = if table.cell.inset == auto { 5pt } else { cell.inset }
let n = counter.get().first()
let (left, right) = (left, right).map(alignment => {
locate(make-label(counter, alignment, n: n)).position()
})
right.x - left.x
}
#let non-expanding-cell(body, ..args, instate: none) = {
mark-cell(cell-counter, ..args, context {
let dx = get-pinned-delta-x(cell-counter)
if instate != none {
instate.update(dx)
}
})
}
#let measuretable(..args) = {
table-counter.step()
context {
let columns = args.at("columns", default: 1)
let columns = if type(columns) == array { columns.len() } else { columns }
let states = range(columns).map(i => state("_measure_col_" + str(table-counter.get().first()) + "_" + str(i)))
let measurecell(st) = non-expanding-cell(inset: 0pt, stroke: none, instate: st)[]
let measurerow = states.map(measurecell)
for st in states { st.update(0pt) }
context {
[Column widths: ]
states.map(st => [#st.final()]).join([, ])
}
std.table(
..args,
..measurerow
)
}
}
#measuretable(columns: 1,
[Abc])
#measuretable(columns: 3, [A], [AB], [ABC])
#measuretable(columns: 1, lorem(10))
#measuretable(columns: 1, lorem(20))
#measuretable(columns: 2, lorem(5), lorem(10))
#measuretable(columns: 2, lorem(10), lorem(5))
#measuretable(columns: 2, lorem(10), lorem(10))
#measuretable(columns: 2, lorem(50), lorem(10))
#measuretable(columns: 2, lorem(10), lorem(70))
#measuretable(columns: 3, lorem(10), lorem(50), lorem(10))
#measuretable(
columns: 3,
)[#lorem(2)][#lorem(5)][#lorem(2)]
#measuretable(
columns: 3,
)[#lorem(80)][#lorem(60)][#lorem(2)]
#measuretable(
columns: 3,
)[#lorem(2)][#lorem(3)][#lorem(4)]
#measuretable(
columns: 3,
block(width: 12cm), [], lorem(2),
)
Looks like it’s about right to me.