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

quarto 1.4 eats LaTeX \providecommand #8564

Open
hughjonesd opened this issue Feb 2, 2024 · 13 comments
Open

quarto 1.4 eats LaTeX \providecommand #8564

hughjonesd opened this issue Feb 2, 2024 · 13 comments
Labels
bug Something isn't working latex LaTeX engines related libraries and technologies tables Issues with Tables including the gt integration third-party Issues involving interaction with a third-party library
Milestone

Comments

@hughjonesd
Copy link

Bug description

Quarto 1.4 causes huxtable tables to fail when compiling to PDF, because it doesn't print out some LaTeX \providecommand commands that huxtable uses. This is new in 1.4.

Steps to reproduce

The following document will fail if compiled to PDF on quarto 1.4.549 or 1.5.6. It works with quarto 1.3.450.

---
title: "Quarto tester"
format: html
---


Reference to @tbl-hux.

```{r}
#| tbl-cap: "Huxtable Jams"
#| label: tbl-hux
library(huxtable)
jams
```

Expected behavior

I'd expect the .tex file produced to have the same \providecommand\huxvb TeX in there as can be seen in the .pdf.md file.

Actual behavior

The \providecommand TeX is not in the .tex file, and as a result xelatex fails with "! Undefined control sequence."

Your environment

No response

Quarto check output

Quarto 1.5.6
[✓] 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.6
      Path: /Applications/quarto/bin

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

[✓] Checking LaTeX....................OK
      Using: TinyTex
      Path: /Users/davidhugh-jones/Library/TinyTeX/bin/universal-darwin
      Version: 2023

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

[✓] Checking Python 3 installation....OK
      Version: 3.11.5
      Path: /Library/Frameworks/Python.framework/Versions/3.11/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: /Library/Frameworks/R.framework/Resources
      LibPaths:
        - /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/library
      knitr: 1.45
      rmarkdown: 2.25

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

cscheid commented Feb 2, 2024

Before I dig in deeper:

---
title: "Quarto tester"
format: html
---

The following document will fail if compiled to PDF

Can you clarify and fix your example?

@cscheid
Copy link
Collaborator

cscheid commented Feb 2, 2024

It'll be hard to make this work in Quarto's new crossref system. Huxtable is emitting its own opinionated crossref entries and those are interfering with Quarto's. The raw LaTeX being emitted here is:

```{=latex}
 
  \providecommand{\huxb}[2]{\arrayrulecolor[RGB]{#1}\global\arrayrulewidth=#2pt}
  \providecommand{\huxvb}[2]{\color[RGB]{#1}\vrule width #2pt}
  \providecommand{\huxtpad}[1]{\rule{0pt}{#1}}
  \providecommand{\huxbpad}[1]{\rule[-#1]{0pt}{#1}}

\begin{table}[ht]
\begin{centerbox}
\begin{threeparttable}
 \label{tab:tbl-hux}
\setlength{\tabcolsep}{0pt}
\begin{tabular}{l l}


\hhline{}
\arrayrulecolor{black}

\multicolumn{1}{!{\huxvb{0, 0, 0}{0}}l!{\huxvb{0, 0, 0}{0}}}{\huxtpad{6pt + 1em}\raggedright \hspace{6pt} Type \hspace{6pt}\huxbpad{6pt}} &
\multicolumn{1}{r!{\huxvb{0, 0, 0}{0}}}{\huxtpad{6pt + 1em}\raggedleft \hspace{6pt} Price \hspace{6pt}\huxbpad{6pt}} \tabularnewline[-0.5pt]


\hhline{}
\arrayrulecolor{black}

\multicolumn{1}{!{\huxvb{0, 0, 0}{0}}l!{\huxvb{0, 0, 0}{0}}}{\huxtpad{6pt + 1em}\raggedright \hspace{6pt} Strawberry \hspace{6pt}\huxbpad{6pt}} &
\multicolumn{1}{r!{\huxvb{0, 0, 0}{0}}}{\huxtpad{6pt + 1em}\raggedleft \hspace{6pt} 1.90 \hspace{6pt}\huxbpad{6pt}} \tabularnewline[-0.5pt]


\hhline{}
\arrayrulecolor{black}

\multicolumn{1}{!{\huxvb{0, 0, 0}{0}}l!{\huxvb{0, 0, 0}{0}}}{\huxtpad{6pt + 1em}\raggedright \hspace{6pt} Raspberry \hspace{6pt}\huxbpad{6pt}} &
\multicolumn{1}{r!{\huxvb{0, 0, 0}{0}}}{\huxtpad{6pt + 1em}\raggedleft \hspace{6pt} 2.10 \hspace{6pt}\huxbpad{6pt}} \tabularnewline[-0.5pt]


\hhline{}
\arrayrulecolor{black}

\multicolumn{1}{!{\huxvb{0, 0, 0}{0}}l!{\huxvb{0, 0, 0}{0}}}{\huxtpad{6pt + 1em}\raggedright \hspace{6pt} Plum \hspace{6pt}\huxbpad{6pt}} &
\multicolumn{1}{r!{\huxvb{0, 0, 0}{0}}}{\huxtpad{6pt + 1em}\raggedleft \hspace{6pt} 1.80 \hspace{6pt}\huxbpad{6pt}} \tabularnewline[-0.5pt]


\hhline{}
\arrayrulecolor{black}
\end{tabular}
\end{threeparttable}\par\end{centerbox}

\end{table}
 
```

We try to detect and correct \begin{table} usage because this means that these tables don't play nicely with our crossreferencing system, but this is a best-effort approach that can't work in all cases. Here, we're getting confused by the \providecommand preamble. (and, in general, we can't detect and handle arbitrary LaTeX in raw code, because parsing LaTeX is impossible).

As a direct example of why we can't support this, the emitted output will never be usable in a Quarto Supplemental Table, because we need to use a different counter than that of the table environment. There are other issues too: note eg the label tab:tbl-hux emitted by huxtable is incorrect.

The fundamental problem here is that huxtable is trying to decide how its table should be crossreferenced, and that's not working with Quarto's expectations of the LaTeX code.

If you can convince huxtable to produce its own captions directly in the code, then you could use that, and remove the tbl-cap entry from your code cell. Then, you could use raw latex references to tab:tbl-hux by typing \ref{tab:tbl-hux} in your Markdown code (that should pass through to LaTeX directly).

@cscheid cscheid added third-party Issues involving interaction with a third-party library latex LaTeX engines related libraries and technologies and removed bug Something isn't working labels Feb 2, 2024
@hughjonesd
Copy link
Author

The text reference @tbl-hux comes out correctly with 1.3.450. What's changed? Huxtable adds "tab:" before knitr labels; It looks like quarto used to rewrite it and remove the "tab:" part. Adding "tab:" was to work with bookdown, IIRC; see https://bookdown.org/yihui/bookdown/tables.html.

In any case, what's breaking TeX compilation is that quarto is removing the \providecommand commands, even though the .md file produced has a block marked as raw LaTeX:

```{=latex}
 
  \providecommand{\huxb}[2]{\arrayrulecolor[RGB]{#1}\global\arrayrulewidth=#2pt}
  \providecommand{\huxvb}[2]{\color[RGB]{#1}\vrule width #2pt}
  \providecommand{\huxtpad}[1]{\rule{0pt}{#1}}
  \providecommand{\huxbpad}[1]{\rule[-#1]{0pt}{#1}}

...

Is there a way I can mark huxtable output as "please leave as is"? If so then I'm happy to make it follow the rules for cross-referencing, if you can explain what these are.

As a process note, I first discovered this when I got a message from CRAN that huxtable was throwing test errors when used with the new quarto. More notice would have been helpful. I've now got 2 weeks to fix this before the package is archived.

@cscheid
Copy link
Collaborator

cscheid commented Feb 3, 2024

What's changed?

All the 1.4 crossref features.

In any case, what's breaking TeX compilation is that quarto is removing the \providecommand commands, even though the .md file produced has a block marked as raw LaTeX:

As I explained in my comment, if we don't attempt to parse that content, things will break in a different way.

Is there a way I can mark huxtable output as "please leave as is"?

Again, as I explained in my comment:

If you can convince huxtable to produce its own captions directly in the code, then you could use that, and remove the tbl-cap entry from your code cell. Then, you could use raw latex references to tab:tbl-hux by typing \ref{tab:tbl-hux} in your Markdown code (that should pass through to LaTeX directly).

More notice would have been helpful. I've now got 2 weeks to fix this before the package is archived.

I'm sorry you're getting hit by this, by that's CRAN policy that we are not involved with and don't control.

@mcanouil
Copy link
Collaborator

mcanouil commented Feb 3, 2024

@hughjonesd See https://quarto.org/docs/prerelease/1.4/ to get a view of "what's changed".

As a process note, I first discovered this when I got a message from CRAN that huxtable was throwing test errors when used with the new quarto. More notice would have been helpful. I've now got 2 weeks to fix this before the package is archived.

May I suggest to use CI to test on Quarto pre-release. You are already using CI (with outdated GitHub Actions). CI is useful precisely for these cases.
Note that your R CMD Checks on GitHub Actions has been failing for more than a year (https://github.com/hughjonesd/huxtable/actions).

@hughjonesd
Copy link
Author

OK, but I'd like people to be able to use the quarto chunk labels, as they can do for bookdown/rmarkdown and could before. It's nicer for the user. Is there a way I can do that? For example, what if I just print the tex label as tbl-hux without the tab: prefix?

More generally, is there a way I can avoid quarto removing the \providecommand? What conditions trigger that? I need some rules to follow, otherwise I am flying blind. If you don't want people to write arbitrary TeX and/or HTML tables via code, OK, but then I think clarify that.

@cscheid
Copy link
Collaborator

cscheid commented Feb 3, 2024

More generally, is there a way I can avoid quarto removing the \providecommand?

Sorry, but that's what I've tried to answer to you twice. If the LaTeX output is not in a cell that Quarto considers part of its native crossref, then you'll have to manage those yourself, and the raw LaTeX should go through unchanged.

@cscheid
Copy link
Collaborator

cscheid commented Feb 3, 2024

If your question is "can I use Quarto syntax and still use huxtable's complex LaTeX code", then the answer is currently no, unless you figure out a way for huxtable to emit LaTeX code that does table formatting without also doing table crossreferencing.

@mcanouil mcanouil added the tables Issues with Tables including the gt integration label Feb 3, 2024
@hughjonesd
Copy link
Author

Right. I'm probably being extremely slow, but could you explain how quarto decides whether a LaTeX table is part of its native crossref? Is it if it emits a \label command? Or is it just anything in a cell with a label: attribute?

@mcanouil
Copy link
Collaborator

mcanouil commented Feb 3, 2024

You need to emit only the table without \label{tab:tbl-hux} which is handled by Quarto.
The label is taken from #| label: tbl-mytable in the code cell.

@cscheid
Copy link
Collaborator

cscheid commented Feb 4, 2024

but could you explain how quarto decides whether a LaTeX table is part of its native crossref? Is it if it emits a \label command?

Our documentation is here: https://quarto.org/docs/authoring/cross-references.html#computations

But, in your case, a code cell with label: tbl-... and tbl-cap: ... will be interpreted by Quarto as a table. There are a numbe of other things that we try to detect for backwards compatibility, and that includes pure LaTeX code with \label{} and \begin{table}. That's ultimately the reason that you're seeing this failure right now; Quarto is trying to take the LaTeX from huxtable and failing to process it appropriately.

@hughjonesd
Copy link
Author

Okay. I did some more testing. Here just for reference is how it works as of 1.4.549:

  • Captions work fine, whether set by quarto or huxtable.
  • Labels starting with tbl- fail to compile, whether set by quarto or huxtable.
  • Labels compile if they don't start with tbl-, but they cannot be referred to by quarto-style @... referencing.
  • Huxtable labels can be referred to by LaTeX-only referencing (\ref{label}), so long as a caption is also set and the label doesn't start with tbl-. Quarto labels don't seem to get picked up.

I'll write code to emit informative errors/warnings.

@hughjonesd
Copy link
Author

An update for 1.5: the following table gets its label eaten, whether or not the label starts with tbl-.

---
title: "quarto minimal table"
format: 
  pdf:
    keep-tex: true
---

Table \ref{foo}.

```{=tex}
\begin{table}[h]
\caption{A table\label{foo}}
\begin{tabular}{l l}
1 & 2
\end{tabular}
\end{table}
```

Table \ref{foo}.

Part of the resulting output:


Table \ref{foo}.

\begin{table}[h]
\caption{A table}
\begin{tabular}{l l}
1 & 2
\end{tabular}
\end{table}

Table \ref{foo}.

Quarto emits a warning.
Quarto version: 1.5.45

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working latex LaTeX engines related libraries and technologies tables Issues with Tables including the gt integration third-party Issues involving interaction with a third-party library
Projects
None yet
Development

No branches or pull requests

3 participants