You can get maximal width for content with measure(this).width
, but you can’t get visually minimal width with measure(this, width: 0pt).width
or measure(block(width: 0pt, this)).width
.
From How can I robustly make (unknown) tables span the full page width? - #2 by Andrew
and How can I robustly make (unknown) tables span the full page width? - #8 by bluss, a solution could be something like this:
/// Get index of partition point
/// - func (function): Return true if less or equal, false if greater than partition point
/// based on rust libcore partition point
#let partition-point(range, func) = {
let size = range.len()
if size == 0 { panic("Empty range in partition-point") }
let base = 0
while size > 1 {
let half = calc.div-euclid(size, 2)
let mid = base + half
let lte = func(range.at(mid))
base = if lte { mid } else { base }
size -= half
}
let lte = func(range.at(base))
base + int(lte)
}
#let estimate-min-width(body) = {
let nominal-length = measure(body).width
let ceil = calc.ceil(nominal-length.pt())
let widths = range(ceil, step: 1)
let pp = partition-point(widths, w => {
let max-width = w * 1pt
let actual-width = measure(body, width: max-width).width
not (actual-width < max-width)
})
let best-guess-max-width = widths.at(pp, default: ceil) * 1pt
measure(body, width: best-guess-max-width).width
}
Then pass any content, e.g., text, to get its min width. But context
is required.
#context estimate-min-width(lorem(50))
This is still an estimation, but it’s better than nothing. You can modify the step part to increase or decrease precision, which in turn can change the compilation time.
2 Likes