The consequences of redefining elementary functions and list of figures generation

This post is a development of the post Incorrect hanging indentation - #6 by aarnent

If you uncomment the line target: figure.where(kind: image), from the code below, you will get the error message where() can only be called on element functions. As a consequence, I cannot display the list of figures. ChatGPT told me that this was a consequence of redefining #figure, an element function.

#set figure.caption(position: top, separator: [ — ])

#let ORIfigure = figure
#let figure(..args, caption: "", source: none, body) = ORIfigure( 
    ..args, 
    caption: caption, 
    body + context block( 
    width: measure(body).width, 
  )[ 
    #set list(marker: "Source:") 
    #show list.item: set align(left) 
    #show list.item: set par(justify: true) 
    #set par(leading: 10pt * 1.15) 
    #set text(size: 10pt) 
    #if source != none { 
      v(-3pt) 
      list.item(source) 
    } 
  ]
)

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

#figure( 
  rect( 
    width: 5cm,
    height: 3cm,
  ),
  caption: [A test figure],
  source: lorem(15)
) <label>

Read @label.

My question is whether it’s possible to use the usual syntax #figure(body,caption,source) <label> and, at the same time, be able to generate a list of figures. Thanks in advance.

Well, this doesn’t answer your question, but you can always use std.figure.where(…). See Using “shadowed” definitions - Typst Documentation.

4 Likes

By the time you are adding the table of contents, figure has already been redefined to your function. The fix is thankfully simple, just reference the original function either using ORIfigure or std.figure.

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