Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Float objects not rendered in PDF after a longtable object #8711

Closed
marklhc opened this issue Feb 12, 2024 · 18 comments · Fixed by #8714
Closed

Custom Float objects not rendered in PDF after a longtable object #8711

marklhc opened this issue Feb 12, 2024 · 18 comments · Fixed by #8714
Assignees
Labels
bug Something isn't working knitr tables Issues with Tables including the gt integration triaged-to Issues that were not self-assigned, signals that an issue was assigned to someone.
Milestone

Comments

@marklhc
Copy link

marklhc commented Feb 12, 2024

Bug description

When making a table with knitr::kable() in R, which gives a longtable object with PDF output, a custom float object in the same document does not work. This has been tested with quarto 1.4.549 and 1.5.10. The custom float object is rendered properly without the longtable object. This may be related to #7604

Steps to reproduce

---
title: "Untitled"
format:
  pdf:
    keep-tex: true
crossref:
  custom:
    - kind: float
      key: out
      latex-env: output
      reference-prefix: Output
---

```{r}
knitr::kable(mtcars)
```

::: {#out-2}

```{r}
#| echo: false
## Example from stats::aov()
aov(yield ~ block + N * P + K, npk)
```

Sample ANOVA output

:::

See @out-2

Expected behavior

The custom float object should be shown.

Actual behavior

I got the error

ERROR: 
compilation failed- error
Missing } inserted.
<inserted text> 
                }
l.307 \end{longtable}

Your environment

  • IDE: VSCode 1.86.1
  • OS: Ubuntu 20.04

Quarto check output

Quarto 1.5.10
[✓] Checking versions of quarto binary dependencies...
      Pandoc version 3.1.11: OK
      Dart Sass version 1.69.5: OK
      Deno version 1.37.2: OK
[✓] Checking versions of quarto dependencies......OK
[✓] Checking Quarto installation......OK
      Version: 1.5.10
      Path: /opt/quarto/bin

[✓] Checking tools....................OK
      TinyTeX: (external install)
      Chromium: 869685

[✓] Checking LaTeX....................OK
      Using: TinyTex
      Path: /home/hokchiol/.TinyTeX/bin/x86_64-linux
      Version: 2023

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

[✓] Checking Python 3 installation....OK
      Version: 3.8.10
      Path: /usr/bin/python3
      Jupyter: (None)

      Jupyter is not available in this Python installation.
      Install with python3 -m pip install jupyter

[✓] Checking R installation...........OK
      Version: 4.3.2
      Path: /usr/lib/R
      LibPaths:
        - /home/hokchiol/R/x86_64-pc-linux-gnu-library/4.3
        - /usr/local/lib/R/site-library
        - /usr/lib/R/site-library
        - /usr/lib/R/library
      knitr: 1.45
      rmarkdown: 2.25

[✓] Checking Knitr engine render......OK
@marklhc marklhc added the bug Something isn't working label Feb 12, 2024
@cscheid
Copy link
Collaborator

cscheid commented Feb 12, 2024

This is even stranger. The mere declaration of the custom crossref format is enough to break longtables.

@cscheid
Copy link
Collaborator

cscheid commented Feb 12, 2024

There appears to be some deep incompatibility between the float latex package (which we need in order to support custom crossrefs) and the longtable package. Honestly, longtable is badly broken in a variety of ways (for example, it hardcodes its crossref counter to table). We already do a large number of workarounds. I unfortunately don't think we can fix this.

I am fairly convinced that this is a bug in longtable, but I don't think it'll be fixed any time soon, and unfortunately both kable and Pandoc emit longtable in their outputs.

@marklhc
Copy link
Author

marklhc commented Feb 12, 2024

Thanks for taking a look @cscheid. I guess I'll have to find a workaround to not use longtable until they fix the issue.

@cscheid
Copy link
Collaborator

cscheid commented Feb 12, 2024

Specifically, this is the definition in our custom float declaration that causes longtable to fail. Note that this has nothing to do with longtables:

\@ifundefined{c@chapter}{\newfloat{output}{h}{loout}}{\newfloat{output}{h}{loout}[chapter]}

This line defines the custom float counter to be top-level if no chapter counter exists, or defines the custom float counter to be a subcounter of chapter if the chapter counter exists. I don't understand how this could possibly interact badly with longtable.

Here's a minimal, pure-latex example:

\documentclass{article}

\usepackage{float}
\newfloat{output}{h}{loout} % <--- This line is the problem

\usepackage{longtable,booktabs,array}
\usepackage{calc}

\begin{document}

\begin{longtable}[]{@{}l@{}}
  \toprule\noalign{}
  \endhead
  \bottomrule\noalign{}
  \endlastfoot
  foo \\
\end{longtable}

\end{document}

This is, to be clear, a huge bummer. We'll work around it on our side to never emit longtables in the presence of custom crossref environments (kable emits markdown tables which we can process differently).

@marklhc
Copy link
Author

marklhc commented Feb 13, 2024

Hi @cscheid, thank you and I see the fix in #8714. However, it seems that longtable is still used when a table caption is added:

---
title: "Untitled"
format:
  pdf:
    keep-tex: true
crossref:
  custom:
    - kind: float
      key: out
      latex-env: output
      reference-prefix: Output
      caption-location: top
---

```{r}
#| label: tbl-1
#| tbl-cap: Table caption
knitr::kable(mtcars)
```

See @tbl-1.

::: {#out-2}

```{r}
#| echo: false
## Example from stats::aov()
aov(yield ~ block + N * P + K, npk)
```

Sample ANOVA output

:::

See @out-2

Would it be possible to use tabular for tables with captions too? Thank you so much.

@cscheid cscheid reopened this Feb 13, 2024
@cscheid
Copy link
Collaborator

cscheid commented Feb 13, 2024

Would it be possible to use tabular for tables with captions too?

That should already be happening (so if it isn't, it's a bug on us).

@cscheid
Copy link
Collaborator

cscheid commented Feb 13, 2024

I can't get your document to render because kable seemingly fails for me with a knitr error message:

processing file: 8717.qmd
1/2
2/2 [unnamed-chunk-1]
output file: 8717.knit.md

Error: Functions that produce HTML output found in document targeting docx output.
Please change the output type of this document to HTML.
If your aiming to have some HTML widgets shown in non-HTML format as a screenshot,
please install webshot or webshot2 R package for knitr to do the screenshot.
Alternatively, you can allow HTML output in non-HTML formats
by adding this option to the YAML front-matter of
your quarto file:

  prefer-html: true

Note however that the HTML output will not be visible in non-HTML formats.

Execution halted

I don't know when kable decides to emit html tables vs markdown, but it seems that you're running a different version than I am (I'm on knitr 1.45).

@cderv will know more, but he's not available in the next few days.

@cscheid cscheid added the triaged-to Issues that were not self-assigned, signals that an issue was assigned to someone. label Feb 13, 2024
@marklhc
Copy link
Author

marklhc commented Feb 13, 2024

That's odd. I'm also on knitr 1.45 and using the developmental version of quarto. I got the same error of

ERROR: 
compilation failed- error
Missing } inserted.
<inserted text> 
                }
l.311 \end{longtable}
                      

see test-float-1.log for more information.

Render is fine without

#| tbl-cap: Table caption

@mcanouil

This comment has been minimized.

@cscheid
Copy link
Collaborator

cscheid commented Feb 13, 2024

I don't understand why knitr does that, tbqh. But I can repro your issue by switching to our div syntax.

@mcanouil mcanouil added knitr tables Issues with Tables including the gt integration labels Feb 14, 2024
@marklhc
Copy link
Author

marklhc commented Feb 14, 2024

Thanks for making another fix @cscheid, and I feel bad for making another report on the same issue . . . but here it is, for regular markdown tables:

---
title: "Untitled"
format:
  pdf:
    keep-tex: true
crossref:
  custom:
    - kind: float
      key: out
      latex-env: output
      reference-prefix: Output
---

| Default | Left | Right | Center |
|---------|:-----|------:|:------:|
| 12      | 12   |    12 |   12   |
| 123     | 123  |   123 |  123   |
| 1       | 1    |     1 |   1    |

: Demonstration of pipe table syntax

::: {#out-2}

```{r}
#| echo: false
## Example from stats::aov()
aov(yield ~ block + N * P + K, npk)
```

Sample ANOVA output

:::

See @out-2
ERROR: 
compilation failed- error
Package caption Error: \caption outside float.

See the caption package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              
                                                  
l.153 \caption
              {Demonstration of pipe table syntax}

The tex file now has the caption outside of the tabular environment in the developmental version of quarto. It also results in a error with quarto 1.4/1.5 as it uses the longtable environment. I also checked that the file rendered correctly without the table caption.

@cscheid
Copy link
Collaborator

cscheid commented Feb 15, 2024

Thank you for the continued reports! We're the one to be apologizing. We'll look at this right away.

@cscheid
Copy link
Collaborator

cscheid commented Feb 15, 2024

So this is tricky. What's happening here is that we can't emit longtable environments because that package doesn't work with the float packages.

When the float package is disabled, Pandoc emits tables always through the longtable environment. That environment is unique in that it's both displays a table, and increments the table latex counter specifically (this is why we already originally disabled longtables inside custom crossrefs). To make matters more complicated, LaTeX doesn't support captions at all outside floats, and so the standard code we use for rendering tabular environments assumes that the code will be emitted inside a float, and issues a \caption{} command.

So now we have to decide what to do when we see a Table outside of a float with a caption, which needs to be rendered with tabular. In Quarto 1.3, the unlabeled table would increment the counter table (because that's what longtable does). Here, though, I'm not sure what we should do. In HTML, we have custom code to render tables and figures with captions but no labels. In LaTeX, this just isn't a thing that really exists.

One solution is to wrap the code in a \begin{table} environment, so that the counter is incremented just like longtable would. I don't love it (because it's unintuitive and makes the counters in LaTeX and HTML inconsistent), but it seems less bad than dropping the caption or attempting to render it by ourselves.

Another solution is for us to create a "hidden" float environment for these unlabeled tables, and configure its captions to not show any counter information. That is closer to what Quarto does in HTML, but will probably confuse users expecting the old behavior.

@marklhc
Copy link
Author

marklhc commented Feb 15, 2024

Hi @cscheid, I just found out that if I don't call the new latex environment as output, it renders correctly:

---
title: "Untitled"
format:
  pdf:
    keep-tex: true
crossref:
  custom:
    - kind: float
      key: out
      latex-env: abc
      reference-prefix: Output
---

```{r}
#| label: tbl-1
#| tbl-cap: Table caption
knitr::kable(mtcars)
```

See @tbl-1.

::: {#out-2}

```{r}
#| echo: false
## Example from stats::aov()
aov(yield ~ block + N * P + K, npk)
```

Sample ANOVA output

:::

See @out-2

So maybe it's just because of the name I chose?

@mcanouil
Copy link
Collaborator

mcanouil commented Feb 15, 2024

The example you shared also works with "output" (it was fixed, for instance your original example works on the latest version of Quarto), but #8711 (comment) won't work whatever the name of latex-env is.

The issue is not as simple as a name thing.
It's a,LaTeX packages conflict.

@marklhc
Copy link
Author

marklhc commented Feb 15, 2024

Sorry I should have clarified: the original example works with the current release of quarto 1.4 or 1.5, before fixing the longtable issue in #8714, once I changed latex-env to something other than "output." So it seems longtable breaks because I call the float object "output." For example, in the minimal example @cscheid shared with longtable and float, xelatex works when I use another name:

\documentclass{article}

\usepackage{float}
\newfloat{abc}{h}{loout} % <--- use a different name than "output"

\usepackage{longtable,booktabs,array}
\usepackage{calc}

\begin{document}

\begin{longtable}[]{@{}l@{}}
  \toprule\noalign{}
  \endhead
  \bottomrule\noalign{}
  \endlastfoot
  foo \\
\end{longtable}

\end{document}

@cscheid
Copy link
Collaborator

cscheid commented Feb 16, 2024

@marklhc is correct, and this enables a good fix for us, happily; PR is up. Thank you for the careful, precise debugging work here, @marklhc!

cscheid added a commit that referenced this issue Feb 16, 2024
@cscheid
Copy link
Collaborator

cscheid commented Feb 16, 2024

I'll daringly call this fixed now, but please let us know if it rears its head again!

@cscheid cscheid closed this as completed Feb 16, 2024
@mcanouil mcanouil added this to the v1.5 milestone Jun 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working knitr tables Issues with Tables including the gt integration triaged-to Issues that were not self-assigned, signals that an issue was assigned to someone.
Projects
None yet
4 participants