How to increase the spacing between the number and the title of a heading?

I say it is great :face_holding_back_tears: your approach is way more elegant as it doesn’t make it necessary to reassemble the links. Thank you very much!

Maybe you had another version of your code that made the first level bold, because in the pasted example, that doesn’t seem to be the case?

So this is what I ended up with:

// style outline
#show outline.entry: entry => {
  if entry.element.func() == heading {
    // because we modify entries by replacing them with new ones, we need to recognize them to avoid endless recursion
    if entry.at("label", default: none) == <modified-outline-entry> {
      entry
    } else {
      // we destructure entry, change fields and then reassemble the entry
      let fields = entry.fields()
      let he = fields.element
      let number = if he.numbering != none {
        numbering(he.numbering, ..counter(heading).at(he.location()))
      }
      let prefix = if number != none [ #number #h(0.8em) ]
      fields.body = [ #prefix #he.body ]
      let newe = outline.entry(..fields.values())
      if entry.level == 1 {
        [ *#newe <modified-outline-entry>* ]  
      }
      else if entry.level == 3 {
        [ #h(0.6em) #newe <modified-outline-entry> ]
      }
      else {
        [ #newe <modified-outline-entry> ]  
      }
      v(-0.4em, weak: true)
    }
  } else {
    entry
  }
}

Basically just adding/changing this part:

      if entry.level == 1 {
        [ *#newe <modified-outline-entry>* ]  
      }
      else if entry.level == 3 {
        [ #h(0.6em) #newe <modified-outline-entry> ]
      }
      else {
        [ #newe <modified-outline-entry> ]  
      }
      v(-0.4em, weak: true)

To:

  • Make level 1 bold
  • Correct the level 3 indent (this wasn’t in the original question/case it come up once I added a level 3 headline in my paper :sweat_smile:)
  • Add vertical spacing (still in the weird negative way, but hey
 it works)

Overall this feels like a lot of hassle to style outlines currently, especially since even the outrageous package suffers from some of the problems (especially the unwanted line break if a space is added between prefix-number and body).

But I think your solution is as good as currently possibly. So everybody landing here, please give issues like the on of PgBiel Add outline spacing/gutter · Issue #1424 · typst/typst · GitHub some thumbs up :up::smiling_face:

The result:

Some further thoughts on your last code snippet:

A)
I prefer to change the weight or add a strong function. This makes it more obvious what is different in the two cases:

#{
      let w = if entry.level == 1 { "bold" } else { "regular" }
      text(weight: w)[ #newe <modified-outline-entry> ] 
}

But this is probably really just preference.

B)
I saw that you added another case for level == 3 with even more indent. Maybe you should then use a separate function to control the indent:

#let indent_func = i => {
  (0em, 1.5em, 3.6em).at(i)
}
#outline(indent: indent_func)

This again separates the different logical units.

Output

1 Like

Wow, thanks again, great additions.

But this is probably really just preference.

No, no, I actually asked about exactly that case above. So how it could be improved/reduced the repetitiveness. So perfect, learned something, I wondered a couple of times how others solve these cases.

#let indent_func = i => {
  (0em, 1.5em, 3.6em).at(i)
}
#outline(indent: indent_func)

Black magic. How does that even work :open_mouth: i
 no loop, no count up, no nothing?

(Now our discussion is not about the original topic anymore xD)

My intuition told me that the devs probably added the option to provide a function for the outline indent 
 and indeed they did: Outline Function – Typst Documentation

I think the part in the documentation about the function is very well written. You can provide a function that takes one number as argument and returns a relative length or even content. (I think the documentation is mostly very worth to read and often provides answers. If you are used to this.)

So i defined the function indent_func. In it I create an array with 3 elements and return the element at position i, which is the level of the entry.

All three following code snippets should be equivalent to the above:

#let arr = (0em, 1.5em, 3.6em)
#let func(i) = arr.at(i)
#outline(indent: func)

and

#outline(indent: i => (0em, 1.5em, 3.6em).at(i))

I like this the most:

#let indent_func(i) = (0em, 1.5em, 3.6em).at(i)
#outline(indent: indent_func)

(That being said: my original function is somewhat ugly as it states an anonymous function which is then given an explicit name.)

If you are not familiar with the concepts used here, you might want to read about:

1 Like

(Now our discussion is not about the original topic anymore xD)

Well, it explains how the solution works :blush: thanks for taking the time to explain!

And for anyone landing here because you want the number of your outline indented/add space before the numbering, make the level 1 headings bold and horizontally align the levels in the outline. Here is the refactored code you can copy and paste:

(Adjust em-values as needed)

#show outline.entry: entry => {
  if entry.element.func() == heading {
    // because we modify entries by replacing them with new ones, we need to recognize them to avoid endless recursion
    if entry.at("label", default: none) == <modified-outline-entry> {
      entry
    } else {
      // we destructure entry, change fields and then reassemble the entry
      let fields = entry.fields()
      let he = fields.element
      let number = if he.numbering != none {
        numbering(he.numbering, ..counter(heading).at(he.location()))
      }
      let prefix = if number != none [ #number #h(0.5em) ]
      fields.body = [ #prefix #he.body ]
      let newe = outline.entry(..fields.values())
      let w = if entry.level == 1 {
        "bold"
      } else {
        "regular"
      }
      text(weight: w)[ #newe <modified-outline-entry> ]
      v(-0.4em, weak: true)
    }
  } else {
    entry
  }
}

#let indent_level(i) = (0em, 1.575em, 4em).at(i)
#outline(indent: indent_level)

PS: @PgBiel since this topic evolved from numbering and adjusting the spacing of headlines to also control said spacing in the outline, but provides solutions for both now, maybe it would make sense to rename the topic to reflect that? :smiling_face: