How do I conditionally include heading name and number in custom ref show rule better?

Hi all,

I wrote a ref show rule to be able to link to strong and emph elements, as I intermittedly use them for subsections. Now, I do have something that seems to work as it should, but it frankly looks like a mess and I have to believe there is a much better way to do this. I tried my best but things like context and query-ing are not really clicking just from reading the reference, so I thought I’d ask if anyone here knows of a better way to write this rule?

I wanted to achieve the following behaviour:

  • If referencing an element that is under the same heading, only display a supplement “section” and its body.

  • If referencing an element that is under a different heading, display the heading supplement and its number as well as “section” and its body.

Here’s an example:

#set text(font: "Source Sans Pro", size: 10pt, lang: "EN")
#set heading(numbering: "1.1", supplement: "Chapter")

= Heading 1

*Subsection 1* <sub-1>

This section has a reference to the following subsection (see @sub-2)

*Subsection 2* <sub-2>

This section has a reference to a subsection outside of its own heading (see @sub-outside)

= Heading 2

*Subsection* <sub-outside>

With result:

Here is what I have now:

#show ref: it => {
  let el = it.element
  if el == none or (el.func() != emph and el.func() != strong) { return it }
  let heading_at = counter(heading).display(at: el.location())
  let heading_here = counter(heading).display(at: here())
  if heading_at != heading_here {
    let heading_name = query(selector(heading).before(el.location())).last().supplement
    return link(el.location(), [#heading_name #heading_at section #el.body])
  }
  link(el.location(), [section #el.body])
}

Any help would be greatly appreciated! Feel free to leave some links behind to reference pages if applicable. Thank you!

I think the code for the references is probably about as good as it gets, dealing with counters and queries is going to be ugly basically no matter what (though you do not have to display the counter, getting their values at the locations suffices).

What I don’t understand is using strong/emph for displaying subsections. Is there a good reason for you to be doing this, beyond easier styling? In general, you should avoid re-inventing the wheel and instead re-style default elements since this allows typst to better understand what is happening in your document and generate more accessible PDFs. See e.g. Accessibility Guide - Typst Documentation