How to avoid nested enum items breaking at the end of the page?

You were already on the right track to try to #show enum.item: set block(breakable: false) – this would, if enum items were implicitly wrapped in a block, make that block non-breakable. This works e.g. for tables. Enum items are not implicitly blocks, however (at least it seems so).

Adding a block within the show rule doesn’t work because it resets numbering, as you have already noticed:

#show enum.item: block.with(breakable: false)

The trick is to not wrap the enum item in a block, but the enum item’s body. You can inspect your current content by wrapping it in repr() and you’ll see that an enum item looks e.g. like this:

item(
  body: sequence(
    [Some question],
    parbreak(),
    item(body: [First answer]),
    // etc.
  ),
)

So if the body was an unbreakable block, this would work. However, the naive way of doing that also leads to a problem:

#show enum.item: it => {
  let (number, body, ..fields) = it.fields()
  body = block(breakable: false, body)
  enum.item(number, body, ..fields)
}

maximum show rule depth exceeded

Each show rule application creates a new enum item, on which the show rule is applied again… With one extra line to return the original item if it’s already the result of this show rule, it works:

#show enum.item: it => {
  let (number, body, ..fields) = it.fields()
  if body.func() == block { return it }

  body = block(breakable: false, body)
  enum.item(number, body, ..fields)
}
2 Likes