How to display a short version of a heading inside the header?

I have very long titles in a document and I would like to have shorter versions in the header.

Example:

= Chapter 1: My chapter title is very long and I want a shorter title in the header

If possible, I would like to have a short and a long string for each chapter: the long string in the body of the document and the short string in the header.

I don’t know how to do this with the hydra package or just typst.

#let chapter(long_title:"", short_title:"") = {
	[= #long_title]
}

#chapter(long_title:"= Chapter 1: My chapter title is very long and I want a shorter title in the header", short_title:"My short title")

How to do have short_title in the header ?

Hello @jlb, this is possible using a combination of queries in the page header. You will find below a full example that also supports numbering, which is trickier in the header as it is right before the heading.

Queries are very powerful indeed, don’t hesitate to play with them. You can also inspect the content of queries directly by hovering over the variable. See

#set heading(numbering: "1.1")
#show heading.where(level: 1): set heading(supplement: "Chapter")
#set page(header: context {
  let h = query(selector(heading.where(level: 1)).before(here()))
  if h.len() == 0 {
    h = query(selector(heading.where(level: 1)).after(here())).first()
  } else {
    h = h.last()
  }
  let s = query(selector(metadata).after(h.location())).filter(it => it.value.children.first().text  == "h:").first()
  let short = s.value.children.slice(1).first()
  align(center, {
    h.supplement
    " "
    if h.numbering != none { numbering(h.numbering, ..counter(heading).at(s.location())) }
    [ -- ]
    short
  })
})
#let chapter(long, short) = {
  heading(long) 
  metadata("h:" + short)
}

#chapter[This is a very long title][Short 1]

#pagebreak()

#chapter[Long][Short 2]

Thanks a lot.

But it doesn’t work with this markup :

#chapter[Long title 1][Short 1]
#lorem(2000)

#chapter[Long title 2][Short 2]
#lorem(2000)

#chapter[Long title 3][Short 3]
#lorem(2000)

I updated the implementation to fix this :smiley:. It was missing edge cases, thanks for the reply

Sorry, I have another problem with this markup :

#chapter[Long title 1][Short 1]
#lorem(2000)

#chapter[Long title 2][Short 2]
#lorem(2000)

#chapter[Long title 3][Short 3]
#lorem(2000)

“Chapter 1 - Short 1” header with "“Chapter 2 - Short 2” heading

Hmmm, I think that should be achievable by checking the page number to ensure correctness. I don’t have time atm, so if someone else passes by, feel free to try.

Hi,

here is a solution using hydra.

#import "@preview/hydra:0.5.1": hydra, selectors
#import selectors: custom

#let chapter(long, short) = {
  [#metadata(short)<short>]
  heading(long)
}

#set page(
  header: context hydra(
    skip-starting: false,
    custom(<short>),
    display: (_, elem) => {
      elem.value
    }
  )
)

#chapter[Long title 1][Short 1]
#lorem(2000)

#chapter[Long title 2][Short 2]
#lorem(2000)

#chapter[Long title 3][Short 3]
#lorem(2000)
2 Likes

Yes, it works, thanks a lot.