How to get line numbers that are regularly spaced and whose values do not depend on their font size?

Here is a MWE:

#let content = [
  #lorem(28)
  δ$attach("C", tl: "13", br: "VPDB", tr: "foobar")$
  #lorem(20)
]

#set par.line(numbering: i => text(size: 1em, fill: red)[#i])
#content

#set par.line(numbering: i => text(size: 0.95em, fill: blue)[#i])
#content

This renders as:

Clearly, the line numbering algorithm is confused by the superscripts and subscripts in the text: one version renders with 4 numbered lines, the other with 5. Moreover, the vertical spacing is all wrong.

That seems like a big problem for using Typst for scientific manuscripts. Is there an obvious solution that I’m missing?

1 Like

While testing with this I observed that a simpler $X^Y_Z$ does not exhibit the same behavior. The problem, it turns out, are the quotes. I know there has been some discussion that strings in math are kinda hard to interpret, and it seems this is another case this comes up. You can avoid your problem by using upright, at the cost of slightly different typesetting – whether that is acceptable depends on whether your attachments are multiple letters or actual words.

EDIT: I just found a solution for regular text, i.e. one that is appropriate for words in sub/superscript. Included in the examples

Reproduction & solution code
#let content = [
  #let nonum(body) = { set par.line(numbering: none); body }
  ... \
  problem: $"XY"^"YZ"_"XZ"$ \
  ... \
  no problem: $X^Y_Z$ \
  ... \
  upright: $upright(X Y)^upright(Y Z)_upright(X Z)$ \
  ... \
  unnumbered: $#nonum[XY]^#nonum[YZ]_#nonum[XZ]$ \
  ...
]

#set page(width: auto, height: auto, margin: (left: 8mm, right: 2mm, rest: 3mm))

#set par.line(numbering: i => text(size: 11pt, fill: red)[#i])
#text(11pt, content)

#pagebreak()

#set par.line(numbering: i => text(size: 11pt, fill: blue)[#i])
#text(12pt, content)

#pagebreak()

#set par.line(numbering: i => text(size: 7pt, fill: green)[#i])
#text(18pt, content)

Not numbering the texts can also achieved by a show rule:

#show math.equation.where(block: false): set par.line(numbering: none)
2 Likes

There’s also something unexpected happening with the size of the numbering:

#let content = lorem(48)

#set par.line(numbering: i => text(size: 1.98em, fill: red)[#i])
#content

#set par.line(numbering: i => text(size: 1.99em, fill: blue)[#i])
#content

image

I would expect the too-big numbers to stack on top of each other, or throw a compilation warning/error.

3 Likes

It seems the way typst determines what paragraph line is and isn’t numbered is dependent on the size of the paragraph numbering, for some reason.
Setting the numbering to be “tall”

#set par.line(numbering: i => align(bottom, box(height: 20pt)[#i]))

produces similar result to what @gezepi observed:

But changing the box height to 0pt duplicates some numbering:

#set par.line(numbering: i => align(bottom, box(height: 0pt)[#i]))

Even weirder (to me), getting rid of the alignment inside numbering gets rid of this issue for the small boxes.

Content
#let content = [
  #lorem(28) \
  $attach("C", tr: "t")$\  // two numbers
  $attach(attach("C", tr: "t"), tr: "t")$\ // three numbers
  #lorem(20) $C^t^t^T^T^T$ $c'$  // okay
]

I just updated my original reply – in retrospect, the solution is pretty clear: you can set par.line(numbering: none) for the offending texts, or for “paragraphs” inside inline equations in general!