So I played around with this a bit and got something I can live with:
#show raw.where(lang: "transcript"): it => {
let (lines, ..fields) = it.fields()
let is-speaker(line) = {
let t = line.trim()
t.ends-with(":")
}
let speaker-name(line) = {
line.trim().slice(0, -1)
}
assert(
lines.len() > 0 and is-speaker(lines.first().text),
message: "transcript must start with a speaker label"
)
let rows = ()
let current-speaker = speaker-name(lines.first().text + ":")
let first-line = true
for line in lines.slice(1) {
let txt = line.text
if is-speaker(txt) {
current-speaker = speaker-name(txt) + ":"
first-line = true
continue
}
rows.push((
if first-line { current-speaker } else { "" },
txt,
))
first-line = false
}
let speaker-width = calc.max(
2pt,
..rows.map(r => measure(text(r.at(0))).width),
)
set par(leading: 1.15em)
set par(spacing: 0pt)
set par.line(numbering: n => str(n))
grid(stroke: none,
columns: (speaker-width, 1fr),
column-gutter: 1em,
row-gutter: 1.15em,
..rows.map(((speaker, txt)) => (
[#speaker],
[#txt],
)).flatten(),
)
}
Question
Is there a way to reset the line counter after each transcript? I tried this but couldn’t get it to work: