How to properly work with cross-references and counters?

I was playing with Typst coming from LaTeX, and in LaTeX there are two very important packages for this, zref and hyperref.

In zref I can retrieve the information of multiple counters (or any counter) with the same label. On the other hand, the standard label in TeX just retrieve the information of the last counter that used refstepcounter.

As I did not find this specific information in the documentation, I want to ask some questions about it:

1- How can I make reference for a custom counter that I created?

Exemple: If I use the numbering system I. (i.e., romans), Can I get the counter as standard integer (i.e. 1)?

2 - How can I get the number of any counter (as an integer) in some part of the text?

3 - With the new line numbers, how can I get the current line number in some part of the document?

4 - How can I make a reference to a line number?

Hello and welcome @TheVisibleThing! The docs are difficult to navigate, information is pretty dispersed throughout!

1- How can I make reference for a custom counter that I created?

In the docs, you can read about counter(key)

The counter element serves only one purpose: counting. A counter cannot be referenced by Typst’s ref.

Now, if you want to create a custom element that is both countable and referenceable, you need

Then you will be able to count counter(figure.where(kind: "custom")). See the docs for ref.

How can I get the number of any counter (as an integer) in some part of the text?

See Accessing a counter.

#context counter(heading).get()

With the new line numbers, how can I get the current line number in some part of the document?

The line number is exposed through counter(par.line). However, I can’t seem to access the line number, I’ll have to ask @PgBiel to tag in for this one (if you don’t mind!).

#set par.line(numbering: "1")

#context counter(par.line).get()
Roses are red. \
#context counter(par.line).get()
Violets are blue. \
#context counter(par.line).get()
Typst is there for you.

image

How can I make a reference to a line number?

See this answer by @laurmaedje for TeX’s \pageref.

#let pageref(label) = context {
  let loc = locate(label)
  let nums = counter(page).at(loc)
  link(loc, numbering(loc.page-numbering(), ..nums))
}

Adapting this example for lineref would be as simple as replacing counter(page) by counter(par.line).

Unfortunately, there is no location.line-numbering, so if your line numbering pattern changes throughout your document, best thing would be to update a state variable.

Ideally, you would write something like

#let line-numbering = "1"
#set par.line(numbering: line-numbering)
#let lineref(label) = context {
  let loc = locate(label)
  let nums = counter(par.line).at(loc)
  link(loc, numbering(line-numbering, ..nums))
}

= Lorem <ipsum>

#lineref(<ipsum>)

But I am unable to make counter(page.line) return the correct line number.

It is not. The line number counter is not public at the moment, and counter(par.line) is not used for anything. Sorry!

This is because the line number counter is special. It is not stepped in the document flow, but outside of it, within the page margins; there, it is stepped exclusively based on the height of the associated lines, so its value does not respect the positions of the lines in the document tree, just their height. For example, if you write LineA #place(dy: -5em)[LineB], LineB will be numbered “1.” while LineA will be numbered “2.” because LineB appeared visually above LineA. For usual counters, the opposite would happen, regardless of the visual appearance.

In addition, having, for example, 5 lines doesn’t mean you will have lines numbered from 1 to 5. If they have the same height, they will collapse into one line number.

Due to this, we cannot expose the line number counter as fetching its value or stepping it within the document flow would be undefined. So, to answer the question:

That is not easily possible at this moment, since line numbers don’t work like other counters, thus they are not exposed.

1 Like