typst
typst copied to clipboard
Short figure caption for outline
Description
Allow adding an optional short caption to be displayed in the outline
Use Case
When adding a caption to a figure, the text might be quite long, in particular, when the figure contains a table or (multiple) images that require explanation. The entire caption text is automatically added to the outline, which may look really messy, depending on the text length.
In the caption package of LaTeX, one can add an argument <list entry>
(kind of a short caption), that shows up in the outline instead of the <heading>
(i.e. the actual caption), if given: \caption[⟨list entry⟩]{⟨heading⟩}
. If no <list entry>
is given, the <heading>
is shown in the outline (as is happening now in typst) and if it is given, but left empty ( \caption[]{⟨heading⟩}
) , no entry will be made in the outline.
I propose changing the heading.outlined
type from boolean
to string/none
. This modification will enable the Table of Contents (ToC) to display a specified string if it is not set to none
.
But then, if it is none is it not showing or is it using the long caption?
See also: https://github.com/typst/typst/pull/1892#issuecomment-1729119959
Here's an idea for a workaround while this isn't implemented yet:
#let outlined-figure(
contents,
label-name,
placement: auto,
caption: none,
outline-caption: none,
) = [
#if outline-caption != none [
#show figure: it => it.counter.update(v => v - 1)
#figure(contents, caption: outline-caption)
]
#figure(
contents,
placement: placement,
caption: caption,
outlined: outline-caption == none,
) #label(label-name)
]
Seems to work and produce the desired result (as far as I can tell).
Here's an idea for a workaround while this isn't implemented yet:
#let outlined-figure( contents, label-name, placement: auto, caption: none, outline-caption: none, ) = [ #if outline-caption != none [ #show figure: it => it.counter.update(v => v - 1) #figure(contents, caption: outline-caption) ] #figure( contents, placement: placement, caption: caption, outlined: outline-caption == none, ) #label(label-name) ]
Seems to work and produce the desired result (as far as I can tell).
This works for me. Thank you!!
Here is another solution that is maybe a little bit less cursed:
#let in-outline = state("in-outline", false)
#show outline: it => {
in-outline.update(true)
it
in-outline.update(false)
}
#let flex-caption(long, short) = locate(loc =>
if in-outline.at(loc) { short } else { long }
)
Which can then be used like this:
#outline(title: [Figures], target: figure)
#figure(
rect(),
caption: flex-caption(
[This is my long caption text in the document.],
[This is short],
)
)
Here is another solution that is maybe a little bit less cursed:
#let in-outline = state("in-outline", false) #show outline: it => { in-outline.update(true) it in-outline.update(false) } #let flex-caption(long, short) = locate(loc => if in-outline.at(loc) { short } else { long } )
Which can then be used like this:
#outline(title: [Figures], target: figure) #figure( rect(), caption: flex-caption( [This is my long caption text in the document.], [This is short], ) )
Working nicely 😄 . Also works for headings:
#heading(level:1, flex-caption(
[ a ver long title a ver long title a ver long title ],
[my short one])
)
Thank you so much!!
Here is another solution that is maybe a little bit less cursed:
#let in-outline = state("in-outline", false) #show outline: it => { in-outline.update(true) it in-outline.update(false) } #let flex-caption(long, short) = locate(loc => if in-outline.at(loc) { short } else { long } )
Which can then be used like this:
#outline(title: [Figures], target: figure) #figure( rect(), caption: flex-caption( [This is my long caption text in the document.], [This is short], ) )
For future reference - this can (obviously) also be used to omit citations inside figure outlines.
#outline(title: [Figures], target: figure)
#figure(
rect(),
caption: flex-caption(
[Some figure showing x @somesource], //Display caption including citation
[Some figure showing x], //Caption without citation used in the outline
)
)
Hi all — I'm new to Typst, so if I should check out some more documentation on my own, please don't hesitate to tell me "just read [XYZ]"!
But I was curious if the new "context" introduced in 0.11.0
will be able to improve the current workaround? I tend to think it can, but I am not entirely sure how. Any advice?
But I was curious if the new "context" introduced in 0.11.0 will be able to improve the current workaround?
Yes, it would now look like this:
#let flex-caption(long, short) = context if in-outline.get() { short } else { long }