How do I highlight text context-dependent in the header section?

Hello there,

I have created a script which dynamically places a 1-row-table of all level-1-headings (called “chapters” in my script) in the header section while keeping equal table column spacings.

#set page(
  header: context {
    let chapters = query(heading.where(level: 1))
    let chap_len = chapters.len()
    
    let i = 0
    let col_spacing = {
      let spacing_array = ()
      while i <= (chap_len - 1) {
        spacing_array.insert(i, (1/chap_len * 1fr))
        i += 1
      }
    spacing_array
    }
  
    show heading.where(level: 1): set text(size: 8pt, weight: "regular")

    table(
      columns: col_spacing,
      align: center,
      ..chapters.flatten()
    )
  }
)

= First chapter

#pagebreak()

= Second chapter

#pagebreak()

= Third chapter

#pagebreak()

= Fourth chapter

#pagebreak()

= Fifth chapter

What I tried next was to highlight (e.g. text weight strong) in the header section the chapter, which is the current chapter in the document on a given page. I experimented with approaches that included something like query(selector(heading).before(here())).last() but I realized I got stuck everytime, basically due to a profound lack of understanding of this whole context universe.

I would be grateful if the community could give me a hint on how to solve this.

Thanks a lot in advance!

One thing that I think is causing you issues is that you are inserting the headings themselves into the table. So when you query for headings again these are also found. The following code only uses the .body field of the heading.
I’ve also simplified the creation of the spacing to (1fr, ) * chapters.len(). The first part defines a list that contains only 1fr, then multiplies that list by the number of chapters. 1fr can be used here because Typst itself calculates how wide a fr should be.

I’ve filled the cell with gray instead of using strong() just to make the difference even more obvious.

#set page(
  header: context {
    let chapters = query(heading.where(level: 1))
  
    set text(8pt, weight: "regular")

    let chapter-pages = chapters.map(ch => ("chapter": ch.body, "page": locate(ch.location()).page()))
    let cur-page = here().page()

    let chapter-to-highlight = chapter-pages.filter(
      c => c.at("page") <= cur-page
    ).last().at("chapter")

    table(
      columns: (1fr, ) * chapters.len(),
      align: center,
      ..chapters.map(
        ch => if ch.body == chapter-to-highlight {
          table.cell(ch.body, fill: gray)
        } else {
          table.cell(ch.body)
        }
      ).flatten()
    )
  }
)

= First chapter
#lorem(20)
#pagebreak()
#lorem(20)
#pagebreak()

= Second chapter

#pagebreak()

= Third chapter

#pagebreak()

= Fourth chapter

#pagebreak()

= Fifth chapter

3 Likes

How cool is that, @gezepi ! Thank you so much! From your response I am learning a lot about how to tackle such problems in general.

1 Like