typst icon indicating copy to clipboard operation
typst copied to clipboard

`figure.caption` `separator` field only exists if set manually

Open MDLC01 opened this issue 1 year ago • 1 comments

Description

Take a look at the following Typst code.

// Replaces any figure by its caption separator.
#show figure: it => {
  it.caption.separator
}

#figure(
  caption: figure.caption(separator: [separator])[caption]
)[figure]

This renders as the word "separator", as expected.

Now, consider the following piece of code:

// Replaces any figure by its caption separator.
#show figure: it => {
  it.caption.separator
}

#figure(
  caption: figure.caption[caption]
)[figure]

This time, no separator is explicitly declared, and the compiler emits the following error message:

content does not contain field "separator"

The same error message is produced with figure(caption: [caption])[figure].

Instead, I would expect the separator field to contain whatever the default separator is where the figure.caption is displayed.

Code analysis

I would have expected this to set the separator before the execution of the show rule:

https://github.com/typst/typst/blob/0f274f8edbbb93d65cb11713f4bdf912b3286800/crates/typst-library/src/meta/figure.rs#L534-L540

This is likely due to the fact that synthesize is not called for the figure.caption when executing the show rule for a figure, because the following Typst code works as I would expect, rendering as a colon:

// Replaces any figure by its caption separator.
#show figure: it => {
  show figure.caption: it => {
    it.separator
  }
  it.caption
}

#figure(
  caption: figure.caption[caption]
)[figure]

Adding the following line in FigureElem::synthesize seems to fix the issue, although I'm not sure this is the right way to do it.

caption.synthesize(vt, styles)?;

Reproduction URL

No response

Operating system

No response

Typst version

  • [X] I am using the latest version of Typst

MDLC01 avatar Nov 01 '23 13:11 MDLC01

To handle this for the caption, it would need to be preprocessed during figure synthesis. This pre-processing would need to include basically the whole preparation stage (so that show-set styles are properly materialized), but without actually marking the implement as prepared (because we can't apply show-set styles beyond materializing the fields: for show figure.caption: set text(blue) there is no place to store the blue style before the caption itself is prepared & shown).

While possible, I'm not sure in how far supporting this now would restrict future design possibilities. There are also other elements like enum.item which would need similar manual pre-processing.

For this reason, I'll leave this out of #3311 for now. I'm not even sure whether I consider it a bug or just behaviour that may or may not be desirable.

laurmaedje avatar Feb 01 '24 13:02 laurmaedje