How to evaluate page header at the start of the page?

Edit: Just had a bit of time off and could restructure this post a bit.

Hello @ykremer , welcome to the forum,

What you are experiencing has been commented on before:

In your particular case, it is not zero, it is none.

Knowing that, there are a few solutions available for you, including but not limited to:

Using Hydra Package

With Typst Headings

Hydra is designed specifically for that purpose. You can use any heading level you want and it is highly configurable.

This is a working example showing the last defined exercise (here we are using level 1 headings) in the header:

#import "@preview/hydra:0.6.2": hydra
#set page(
  header: context {
    hydra(use-last: true, skip-starting: false)
    line(length: 100%)
  },
)
= Exercise 1
= Exercise 2
= Exercise 3

With Custom Element

If you don’t want to use the heading elements, you can define some custom ones for your needs. The key is to define a way for Hydra to display the custom element.

hydra is built with custom elements in mind. Some documents may use other elements for chapters or section-like content. hydra allows defining its own selectors for tight control over how elements are queried.

See Hydra’s documentation for more information.

#import "@preview/hydra:0.6.2": hydra

#let exercise(body, label: none) = {
  show figure: set align(left)
  set figure(numbering: "1")
 
  [#figure(kind: "exercise", supplement: [Exercise], caption: body, none)
    #label]
}

#set page(
  paper: "a5",
  header: context {
    hydra(
      figure.where(kind: "exercise"),
      display: (.., it) => it.caption,
      use-last: true,
      skip-starting: false,
    )
    line(length: 100%)
  },
)
#for n in range(1, 4) {
  exercise([#lorem(1)], label: <n>)
}

Without any Packages

Another Solution using Query

This is adapted from How do I count elements on a page so the result isn't always zero in the header? - #7 by janekfleper and uses query instead of state. No packages are needed.

#let exercise(body, label: none) = {
  show figure: set align(left)
  set figure(numbering: "1")

  [#figure(kind: "exercise", supplement: [Exercise], caption: body, none)
    #label]
}

// Find the last exercise on the current page
#let last-exercise() = {
  let ex = query(figure.where(kind: "exercise"))
  if ex.len() > 0 {
    ex.filter(it => it.location().page() == here().page()).last().caption
  }
}

#set page(
  header: context {
    last-exercise()
    line(length: 100%)
  },
)

#for n in range(1, 4) {
  exercise([#lorem(1)], label: <n>)
}

3 Likes