How to customize the behaviour of how hydra displays a section or heading?

I am using Hydra to display the current chapter’s title. However, I want to customize the output of the hydra() function.

For chapter <nr> <name> the output is “<nr> <name>”. How can I change this to “Chapter <nr>: <name>”?

I’d also like to know if Hydra allows me to determine whether a page is empty. I need this information to hide the header on empty pages.

Thanks in advance!

Hey there, thank you for using hydra!

You can customize the behavior of how hydra displays the section or heading it found by passing a function to its display parameter. It works similar to a show rule, but also receives the internal context object, we’ll ignore this as its not relevant for the question.

Assuming you’re chapters are headings as they usually are you can do it like this:

#set page(header: hydra(display: (_, it) => {
  [Chapter ]
  numbering(it.numbering, ..counter(heading).at(it.location()))
  [: ]
  it.body
}))

The first discarded parameter _ is said context object, the second parameter it is the heading that hydra believes to be relevant at the current position.

I’d also like to know if Hydra allows me to determine whether a page is empty. I need this information to hide the header on empty pages.

Not at the moment, but there are other ways to completely ignore the page header, see here and here for some workaround to skip the header there.

Thanks for the answer, but I don’t get it to work.

a) always shows the correct heading number

hydra(1, skip-starting: false)

b) doesn’t work. Starts with chapter 0, seems to always be one page behind

hydra(1, skip-starting: false, display: (_, it) => {
        "Chapter " + counter(heading.where(level: 1)).display() + ": " + it.body
      })

What am I missing?

Edit: A little more context:

  set page(numbering: "1", number-align: top, header: context{   
    if calc.odd(here().page()) [  
      #hydra(1, skip-starting: false, display: (_, it) => {
        "Chapter " + counter(heading.where(level: 1)).display() + ": " + it.body
      })  
      #h(1fr) 
      #counter(page).display("1")
    ] else [ 
      #counter(page).display("1") 
      #h(1fr) 
      #hydra(1, skip-starting: false, display: (_, it) => {
        "Chapter " + counter(heading.where(level: 1)).display() + ": " + it.body
      }) 
    ]
  })

Oh that’s on me! I actually made a mistake here, the reason the counter is one page behind is that I forgot to pass the correct location to the counter display. It should be numbering(it.numbering, ..counter(heading).at(it.location())). Indeed this is the counter the default display uses too, I forgot about that :sweat_smile:. Keep in mind that this assumes all headings are numbered, you may need additional checks if you change the numbering or include other heading ranges.

I have updated the original answer.

1 Like

Perfect! Thank you :)