quarto-dev / quarto-cli

Open-source scientific and technical publishing system built on Pandoc.
https://quarto.org
Other
3.95k stars 325 forks source link

Conditional content with metadata variable and `#sol-` and `#rem-` doesn't render to pdf. #10782

Closed 314a closed 2 months ago

314a commented 2 months ago

Bug description

There seems to be a main.lua filter issue with conditional content for cross-ref #rem- and #sol- .

Rendering a .qmd file with the following conditional (see below) and the metadata solution: true and solution: false works fine for html output. It fails with solution: false and format: pdf.

::: {#sol-example .content-visible when-meta="solution"}
Solution is visible if metadata element `solution: true`. (see @exr-example). 
:::

My current workaround is splitting the divs into two, which way less elegant.

::: {.content-visible when-meta="solution"}
::: {#sol-example}
Solution is visible if metadata element `solution: true`. (see @exr-example). 
:::
:::

The problem only occurs for the prefix #sol-, #rem- and not for any of the other reserved prefixes such as #exm, #exr, #rem, #def, #thm.. (as listed in Quarto Cross References)

Steps to reproduce

File: exercise.qmd Rendering the following file with quarto render exercise.qmd

---
title: "Conditional Solution Box"
solution: false
format: pdf
---
Show Solution: {{< meta solution >}}, see @exr-example and  @sol-example.

::: {#exr-example}
Exercise to test conditional boxes using metadata variable `solution`.
:::

::: {#sol-example .content-visible when-meta="solution"}
Solution is visible if metadata element `solution: true`. (see @exr-example). 
:::

Expected behavior

A rendered pdf with a hidden #sol-example box.

Actual behavior

Error message, when rendering the file to pdf:

Error running filter C:/Program Files/Quarto/share/filters/main.lua:
C:/Program Files/Quarto/share/filters/main.lua:22821: attempt to index a nil value (field 'integer index')

Your environment

Quarto check output

Quarto 1.5.57
[>] Checking versions of quarto binary dependencies...
      Pandoc version 3.2.0: OK
      Dart Sass version 1.70.0: OK
      Deno version 1.41.0: OK
      Typst version 0.11.0: OK
[>] Checking versions of quarto dependencies......OK
[>] Checking Quarto installation......OK
      Version: 1.5.57
      Path: C:\Program Files\Quarto\bin
      CodePage: 1252

[>] Checking tools....................OK
      TinyTeX: (not installed)
      Chromium: (not installed)

[>] Checking LaTeX....................OK
      Tex:  (not detected)

[>] Checking basic markdown render....OK

[>] Checking Python 3 installation....(None)

      Unable to locate an installed version of Python 3.
      Install Python 3 from https://www.python.org/downloads/

[>] Checking R installation...........OK
      Version: 4.4.1
      Path: C:/PROGRA~1/R/R-44~1.1
      LibPaths:
        - D:/library/rpackages/4.4
        - C:/Program Files/R/R-4.4.1/library
      knitr: 1.48
      rmarkdown: 2.27

[>] Checking Knitr engine render......OK
mcanouil commented 2 months ago

Conditional content should not be mixed with cross-reference div. You have to nest the two.

---
title: "Conditional Solution Box"
solution: false
format: pdf
---
Show Solution: {{< meta solution >}}, see @exr-example and  @sol-example.

::: {#exr-example}
Exercise to test conditional boxes using metadata variable `solution`.
:::

:::: {.content-visible when-meta="solution"}
::: {#sol-example}
Solution is visible if metadata element `solution: true`. (see @exr-example). 
:::
::::
cscheid commented 2 months ago

@mcanouil's suggestion should solve the problem. I'm going to go ahead and close this one.

314a commented 2 months ago

While the nested approach works, it would be good that the behavior across cross references is consistent. Maybe this point is something to aid to the overhaul list for Crossref

Particularly, for exercise templates, it would be a nice feature to be able to conditionally turn solutions on/off with the reference to the exercise with cross-references. While this can be partly solved with custom .lua scripts, the appraoch with conditionals consistent in behaviour with the other crossref prefixes would be preferable.

mcanouil commented 2 months ago

Sorry, hard to understand what you are saying here. Are you saying, mixing conditional with some divs works? This might be a "lucky" result. Would you mind sharing code demonstrating the "inconsistency" you are mentioning?

Note that, as far as I know, there is nowhere in the documentation where conditional content is merged with other fenced divs. Unfortunately, it's not because you have ::: {} that you can merge those. The structure matters.

::: {something}
::: {else}
whatever
:::
:::

is not and will not be equivalent to:

::: {something else}
whatever
:::

Even, if you found some cases where it works, you really should not consider this as the normal/default behaviour.

Particularly, for exercise templates, it would be a nice feature to be able to conditionally turn solutions on/off with the reference to the exercise with cross-references. While this can be partly solved with custom .lua scripts, the appraoch with conditionals consistent in behaviour with the other crossref prefixes would be preferable.

I suggest you go look in GitHub Discussions as this has already been discussed: https://github.com/quarto-dev/quarto-cli/discussions Also, you can look for existing extensions such as "assign": https://m.canouil.dev/quarto-extensions/

314a commented 2 months ago

I tested it for all the reserved prefixes listed in Quarto Cross References. That's why I thought it was a feature, even if it's not explicitly documented. It works for all the reserved prefixes if rendered to html. In the case of rendering to pdf, there's a nul pointer error for the prefixes #sol- and #rem-, the rest is rendered without any issue.

---
title: "Conditional Content Test"
solution: false
format: pdf
---
::: {#sol-example .content-visible when-meta="solution"}
Replacing #sol-example with #exm-example, #exr-example, #def-example, #thm-example .... works.
:::

I will look into the mentioned discussions.