How to hide an outline if there are no entries?

How can I hide and outline if it has no entries to display? I believe I should be able to use #if and #counter to make this work (and maybe #context), but I have not wrapped my head around how counters work.

I have a template I am using to make documents. The template includes the creation of outlines.

  #outline(
    title: [Table of Contents],
  )

  #outline(
    title: [List of Figures],
    target: figure.where(kind: image),
  )

  #outline(
    title: [List of Tables],
    target: figure.where(kind: table),
  )

However, if the document does not use any figures or tables, the outline just prints a title with no entries. In this case, I would like the title to not show at all.

    TABLE OF CONTENTS
1. XXXX
2. XXXX

    LIST OF FIGURES

    LIST OF TABLES

I believe I should be able to do something like

#if (context{counter(figure.where(kind: table)).final()} > 0) [
  #outline(
    title: [List of Tables],
    target: figure.where(kind: table),
  )
]

But I get this error:

$ typst compile main.typ 
error: expected boolean, found content
   ┌─ main.typ:12:4
   │
12 │ #if (context{counter(figure.where(kind: table)).final()} > 0) [
   │     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Thanks!

Your approach will work if you wrap everything in context(). Right now the context will return content (which it always does, see this post if you want to learn more about the details), causing the error on compilation.

Note that counter.final() always returns an array of integers. I therefore had to append .at(0) to get the first element from the array.

#context {
  if counter(figure.where(kind: table)).final().at(0) > 0 {
    outline(
      title: [List of Tables],
      target: figure.where(kind: table),
    )
  }
}

I would also ask you to move your post to the Questions category. The title is already great. :slight_smile:

That worked great, thank you!

I guess #context is what I really need to wrap my head around.

Another simple and more general solution would be to apply a show rule, which only allows the outline to show up when there are elements it could list:

#show outline: it => if query(it.target) != () { it }

You then only have to write this once, and it works for all subsequent outlines, no matter if it targets headings, figures, tables, or something else.

4 Likes