Why is I-figured broken with custom template?

I am currently customizing this template: tgm-hit-thesis – Typst Universe

It is using the i-figured package which is supposed to reset the figure counters on new chapters. Therefore, the first figure in chapter number X should be numbered X.1. But it is not happening and i cannot get it to work.

I am really grateful for any pointers.

I tried the template and it seems like it has section-based figure numbers already built in. So I don’t know what’s the problem and why you would even do it with a separate package then?

Please also share your code.

Thank you for your time.
You are right, the template has section-based figure numbers, using the i-figured package. The catch is, they don’t seem to work for me. I am not trying to include a separate package, as the package is already included in the template.

Try to include two figures in two different chapters. I’d expect the figures to be labelled X.1 and Y.1, but instead they are labelled X.1 and Y.2.

Please see this minimal example of the template with two figures in Chapter 4 and 5: Typst

Ah indeed that’s broken. I don’t know if that’s an issue with i-figured or with the template (and I don’t have the time to go through all the code…), but you can use headcount instead:

#import "@preview/headcount:0.1.0": *

#set heading(numbering: "1.1")

// these two lines set up the figure numbering
#set figure(numbering: dependent-numbering("1.1"))
#show heading: reset-counter(counter(figure.where(kind: image)), levels: 1)

= First chapter

#figure(
  [This is a figure.],
  caption: [And this is a caption.]
)

= Second chapter

#figure(
  [This is a figure in another chapter.],
  caption: [And this is the other caption.]
)

I guess the easiest is to write your complete own template then, which is anyways a good exercise to learn Typst. (You can of course copy some code from the given template.)

Hi,
thank you for your suggestion.
In the meantime, I have manage to figure out that this block in the template messes with the figure numbers:

  // chapters start on a right page and have very big, fancy headings
  show heading.where(level: 1): it => {
    set text(1.3em)
    pagebreak(to: "odd")
    v(12%)
    if it.numbering != none [
      #align(right, { 
        text(6em, fill: gray, style: "normal", { 
          counter(heading).display()
        })
      })
      #parbreak()
    ]
    set text(1.3em)
    v(-4cm)
    align(right)[#text(1cm, weight: "regular")[#it.body]]
    v(0.5cm)
  }

Do you have an idea why that is and how it could be fixed? Interestingly, even doing

  // chapters start on a right page and have very big, fancy headings
  show heading.where(level: 1): it => {}

is enough…

In the meantime, I found the solutions. Simply initializing the i-figured package AFTER the custom heading show rule did the trick. In the template, the init is done before the custom show rule, resulting in the numbering not working properly.

// define show rule
show heading.where(level: 1): it => {
  // custom show rule
}

// init i-figured package
show heading: i-figured.reset-counters
show figure: i-figured.show-figure
show math.equation: i-figured.show-equation

With headcount the order doesn’t matter (and will never matter) :wink:

Hi, template author here! Thanks for figuring (no pun intended) the problem out. I have applied your fix and it will be in the next release! Btw, check out the main branch, as I applied frozolotl’s emtpy page fix, which gets rid of the need to manually insert chapter-end!


Putting on my moderator hat: could you maybe try to revise your post’s title to be a complete question as per the question guidelines:

Good titles are questions you would ask your friend about Typst.

We hope by adhering to this, we make the information in this forum easy to find in the future. Thanks!

That’s great news.

I would love to edit the title, but it seems like there is no option to.

@jbirnick I could not get headcount to work properly with the template.
I have build another example at Typst. Setup of headcount is done in template/lib.typ in line 158. Maybe i was missing something.

Ok I was talking BS, the order does matter for headcount. To fix your template, put the

show heading: reset-counter(counter(figure.where(kind: image)))

after all the other heading show rules (in particular after your “custom heading design”).


If you’re interested, here is an explanation. The reset-counter show rule is something like this

it => {
  thecounter.update((0,))
  it
}

where thecounter is the counter in the argument, so in this case the counter of figure. So it just resets the counter of figure and then displays the heading as usual.

Now the question is, what happens if you put another show rule for heading below the one above. This will “wrap around” the show rule above, in the sense that it in the new show rule is actually:

thecounter.update((0,))
heading(...)

So if you just reuse it in your new show rule, everything will still be fine. For example, this still works:

#import "@preview/headcount:0.1.0": *

#set heading(numbering: "1.1")
#set figure(numbering: dependent-numbering("1.1"))
#show heading: reset-counter(counter(figure.where(kind: image)))

// custom design
#show heading: it => {
  block(fill: green.lighten(20%), inset: 5pt, it)
}

= Introduction

#figure([some figure], caption: [some caption])

= Let's Go

#figure([another figure], caption: [another caption])

The problem now comes when, in your new show rules for your custom design, you do not use (the full) it, but just for example it.body. For example, this doesn’t work:

#import "@preview/headcount:0.1.0": *

#set heading(numbering: "1.1")
#set figure(numbering: dependent-numbering("1.1"))
#show heading: reset-counter(counter(figure.where(kind: image)))

// custom design
#show heading: it => [
  #counter(heading).display() | #it.body
]

= Introduction

#figure([some figure], caption: [some caption])

= Let's Go

#figure([another figure], caption: [another caption])

The reason is that, because your don’t use it as a whole, everything that’s done by previous show rules is not used, so you essentially discard all old show rules.

Putting the reset-counter(...) show rule last fixes this, because then you first apply your custom design, and the reset-counter(...) show rules then makes

thecounter.update((0,))
yourcustomdesign

out of this.

Just for completeness, let me mention that there is a second counter package with a totally different approach, which might be of interest to you to avoid such problems: rich-counters

1 Like

Indeed, this seems related to ✏ Allow editing of old messages - it appears new users can only change the title within 24h. We will change it for you (sorry for the trouble). But please ensure future posts’ titles are full questions. Thank you :slight_smile: