Why do curly braces change the meaning of this code?

I have previously found a solution that allows me to have two things:

  • Chapter headings on the next, odd page, and
  • To remove all page decorations (e.g. page numbers) on any skipped page

The code I have for this is:

#show heading.where(depth: 1): it => {
  {
    set page(background: none)
    pagebreak(to: "odd")
  }
  it
}

What I don’t understand is what the extra set of braces is doing to this function. What I do know is that they are clearly necessary, as the following does not work:

#show heading.where(depth: 1): it => {
  set page(background: none)
  pagebreak(to: "odd")
  it
}

In this case, the heading ends up being on its own, isolated page, and the chapter text doesn’t start until the next page.

As someone coming from a programming background, these braces suggest to me ideas like scope, and in the context of Typst, signal the beginning of a code section. But neither of these seem to account for this difference.

So what’s going on here?

To answer my own question:

The first thing to keep in mind is that #set page(...) will always trigger an implicit page break. This new page will be created whenever a new #set page(...) rule comes into effect, which includes when a short-lived page configuration reverts back to the default configuration.

Secondly, the inner curly braces signal a new scope, and specifically in this case, signal a limited scope for the #set page(...) command.

So what’s happening in the second example, without the inner braces is:

  • The scope of #set page(...) includes the entire block of code, including the heading.
  • When this block returns, the page settings revert to the parent scope, which in turn triggers a new page.
  • This causes the heading and its ensuing body text to be set on separate pages.

When the inner curly braces are added:

  • The scope of #set page(...) is in effect only during the page break.
  • When the scope ends, the parent scope’s page settings come back into effect.
  • And since this page configuration change occurs at the same point as an explicit page break, the implicit page break is forgone.
1 Like