How to conditionally set heading block parameters?

I’ve thought about this as well (e.g., this post where I was hoping to add spacing conditional on what followed the content). I think such conditional typesetting is currently not very easy in Typst. If it were to be done via show rules, I think there would have to be something like a next() function that can be used with context to find what the next element is that follows the current one.

Perhaps there is some way to do this that I’m unaware of (maybe with query), or maybe such functionality is in the works already? Regardless, the best way I can think of solving your issue is to pass all content of the document to a function, which checks the content and inserts spacing around headers conditionally, like below. This code abuses repr and sidesteps Typst’s normal structure for showing. It should not be used.

#let get_header_depth(elem) = {
  if repr(elem.func()) == "heading" { // this abuses repr and should not be used but I don't know an alternative
    return elem.depth
  }
  return none
}

#let add_conditional_header_spaces(txt) = {
  if not txt.has("children") {return txt}
  let elems = txt.children.filter(x => x != [ ])
  for (indx, elem) in elems.enumerate() {
    if get_header_depth(elem) == 1 {
      if indx != elems.len() - 1 and get_header_depth(elems.at(indx + 1)) == 2 {
        [#elem \[SMALL SPACE HERE\] ]
      } else {
        [#elem \[LARGE SPACE HERE\] ]
      }
    } else {
      elem
    }
  }
}

#add_conditional_header_spaces[= hello
#lorem(10)

= goodbye
== a subheading
#lorem(10)

= foo
#lorem(10)
== a subheading
#lorem(10)]

If anyone has suggestions on how conditional seting or showing might be completed based off of neighboring elements I would love to hear it.

1 Like