How to include links to heading labels inside a context function

Hello Typstologists,
Following up from a previous issue I had with context the following is my reprex:

#set page(
  header: context {
    // chapters
    let chap = query(heading.where(level: 1))
    // chapter pages
    let chap-pages = chap.map(
      i => (
        "chapter": i.body,
        "page": locate(i.location()).page()
      )
    )
    // current page
    let curr-page = here().page()
    // highlighted page
    let chap-highlight = chap-pages.filter(i => i.at("page") <= curr-page).last().at("chapter")
   

    if (counter(page).get().at(0) == 1) {
      "This is the header at the first page"
    } else {
      table(
        columns: (1fr, ) * chap.len(),
        align: center,
        ..chap.map(
          i => if (i.body == chap-highlight) {
            table.cell(text(white, i.body), fill: red)
          } else {
            table.cell(i.body)
          }
        ).flatten()
      )
    }
  }
)


= The magnificent first page
#pagebreak()

= Section A
#lorem(300)
#pagebreak()

= Section B
#lorem(300)

I was wondering if there is a way to include a link function in the table.cell of the header. The idea is that the i.body (the heading) is inside a link function which cross-references to the actual position of that heading.

Is that possible?

Cheers,
Amman

When creating the dictionary with info about the chapters, you can include the location:

    let chap-pages = chap.map(
      i => (
        "chapter": i.body,
        "page": locate(i.location()).page(),
        "location": locate(i.location())
      )
    )

Then in the table map that array of dictionaries instead of the chap array so that you can create a link with the location saved earlier

..chap-pages.map(
\\...
table.cell(link(i.location, i.chapter))
Full Code
#set page(
  header: context {
    // chapters
    let chap = query(heading.where(level: 1))
    // chapter pages
    let chap-pages = chap.map(
      i => (
        "chapter": i.body,
        "page": locate(i.location()).page(),
        "location": locate(i.location())
      )
    )
    
    // current page
    let curr-page = here().page()
    // highlighted page
    let chap-highlight = chap-pages.filter(i => i.page <= curr-page).last().chapter
   

    if (counter(page).get().at(0) == 1) {
      "This is the header at the first page"
    } else {
      table(
        columns: (1fr, ) * chap.len(),
        align: center,
        ..chap-pages.map(
          i => if (i.chapter == chap-highlight) {
            table.cell(text(white, link(i.location, i.chapter)), fill: red)
          } else {
            table.cell(link(i.location, i.chapter))
          }
        ).flatten()
      )
    }
  }
)


= The magnificent first page
#pagebreak()

= Section A
#lorem(300)
#pagebreak()

= Section B
#lorem(300)

It might be worth only saving the location then later accessing i.location.page, but I left it as-is.

Thanks a lot! As you suggested, I also just used i.location.page().

1 Like