How to add more fields to figure function?

Hello, I’m trying to create a new field in an existing function, ideally I want to add a note field to my figures so they look like this:


with a code like this:

#figure(
    image("imagenes/panda.jpg", width: 60%),
    caption: [A picture of a panda],
    note: [Source: trust me] //<- custom field
)

Right now the code that I’m using looks like this:

#figure(
    image("imagenes/panda.jpg", width: 60%),
    caption: [A picture of a panda]
)

#pad(x: 0in)[#set text(size: 10pt); Source: trust me]

and the code for my figures like this:

 #show figure: it => {
    set par(first-line-indent: 0mm)

    let caption_content = if it.caption != none {
      align(left)[
        *#it.supplement #it.counter.display():*
        #text(weight: "regular", style: "italic")[\ #it.caption.body]
      ]
    } else {[]}

    let fig_content = align(center)[
      #it.body 
    ]

    block([#caption_content #fig_content], width: 100%)
  }

Thanks!

Hello @FelCar! Unfortunately, you cannot add a field to figure.

If the note you want to add must be after the figure itself, then your code is the right way to do this. you can simply wrap the note in a function called figure-note and call it after the figure.

#let figure-note(body) = pad(x: 0in, text(10pt)[Source: #body])
#figure(
    image("imagenes/panda.jpg", width: 60%),
    caption: [A picture of a panda]
)
#figure-note[trust me]

Inspired by @quachpas’s solution and this post from @Andrew, figure can be redefined to include a custom field:

#show figure: set block(width:100%)
#show figure: set figure.caption(position: top)
#show figure.caption: it => align(left)[
  *#it.supplement
  #context it.counter.display(it.numbering)#it.separator*\
  #emph(it.body)
]
#let figure(note: none, body, ..args) = std.figure(..args, {
  body
  set text(size: 10pt)
  set align(left)
  [Source: ] + note
})

#figure(
  rect(width: 5cm, height: 5cm),
  caption: [A picture of a panda],
  note: [trust me], //<- custom field
)

I’ve replaced image(...) with rect() so the example would compile.

3 Likes

That’s a good solution! The only nitpick I have is that by redefining std elements, you prevent the LSP from doing its job :frowning: (it also increases the chances of forgetting that figure is not std.figure.

Very true. :thinking: Perhaps

#let cust-figure(...) = std.figure(...)

would be a better solution or at least it would be clear.

Thanks, I think this is the best way, but I renamed it instead of overriding figure as @quachpas suggested.

A related question is how to display the note in an outline of the figures, instead of the caption. I found this post for a way to display a list of figures , but there you get the whole caption.