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

Math formatting does not work in styled KableExtra tables #555

Open
meghanto opened this issue Apr 6, 2022 · 9 comments
Open

Math formatting does not work in styled KableExtra tables #555

meghanto opened this issue Apr 6, 2022 · 9 comments
Labels
bug Something isn't working knitr math any issue related to math support in specific formats tables Issues with Tables including the gt integration third-party Issues involving interaction with a third-party library
Milestone

Comments

@meghanto
Copy link

meghanto commented Apr 6, 2022

I am using Quarto 0.9.180 with Pandoc 2.5

Here is a sample qmd file

---
title: "Test"
format: html
---

```{r}
data <- data.frame(X1 = c(1,2,3,4), 
                   X2 = c(5,6,7,8), 
                   X3 = c(9,10,11,12), 
                   Y = c('R', 'R','G', 'R'), 
                   stringsAsFactors = F)

colnames(data) <- c('$X_{1}$', '$X_{2}$', '$X_{3}$', '$Y$')

library(knitr)
library(kableExtra)

kable(data, row.names = TRUE) %>%
   kable_styling(bootstrap_options = "striped", full_width = F)

```

And here is the corresponding rmd file.

---
title: "Test"
output: html_document
---

```{r}
data <- data.frame(X1 = c(1,2,3,4), 
                   X2 = c(5,6,7,8), 
                   X3 = c(9,10,11,12), 
                   Y = c('R', 'R','G', 'R'), 
                   stringsAsFactors = F)

colnames(data) <- c('$X_{1}$', '$X_{2}$', '$X_{3}$', '$Y$')

library(knitr)
library(kableExtra)

kable(data, row.names = TRUE) %>%
   kable_styling(bootstrap_options = "striped", full_width = F)
```

The two html outputs are here.
The quarto output does not render the math.

@cderv
Copy link
Collaborator

cderv commented Apr 7, 2022

Thanks for the report.

I believe this happens because in Quarto the HTML table is inserted as a raw HTML block using

```{=html}
# HTML table here
```

whereas with R Markdown, it is inserted directly in the markdown document without raw block.

This allows the Pandoc's extensions markdown_in_html_blocks to apply (https://pandoc.org/MANUAL.html#extension-markdown_in_html_blocks) - that is thanks to this extensions that the Math are converted by Pandoc.
Deactivating the extensions will gave the same results as in Quarto

output: 
  html_document:
    md_extensions: -markdown_in_html_blocks

This extensions won't apply in HTML code inserted in Raw content block. This explain why Quarto does not give the same results.

For now, you would need to try other table framework, or use markdown tables and not HTML ones.

We need to see where the fenced part are added and if we could make an exception somehow... 🤔
@dragonstyle to you know if we are the ones adding those raw block as we detect HTML ?

Nevermind - found it. We are specifically inserting kable() results in raw block.

# patch knitr_print.knitr_kable to enclose html output in pandoc RawBlock
knitr_raw_block <- function(x, format) {
knitr::asis_output(paste0("\n\n```{=", format, "}\n", x, "\n```\n\n"))
}
knitr_kable_html <- knitr:::kable_html
kable_html <- function(...) {
x <- knitr_kable_html(...)
knitr_raw_block(x, "html")
}

This definitely prevent using markdown content inside the table cell.

@jjallaire
Copy link
Collaborator

The reason we are doing this is so that all of our tbl-cap, tbl-subcap, and cross-reference features work (because if its not in a raw block then the table isn't parsed coherently by pandoc). So even if we provide a way to selectively disable this behavior it will break cross references and table captions (not sure if that's a good tradeoff).

This code does work (but is not full width):

``{r}
data <- data.frame(X1 = c(1,2,3,4), 
                   X2 = c(5,6,7,8), 
                   X3 = c(9,10,11,12), 
                   Y = c('R', 'R','G', 'R'), 
                   stringsAsFactors = F)

colnames(data) <- c('$X_{1}$', '$X_{2}$', '$X_{3}$', '$Y$')

library(knitr)
kable(data, row.names = TRUE)
```

We have an intermediate term work item to provide additional ability to customize bootstrap table output (which could encompass the full width option). I'm more inclined to enhance our ability to customize table output than to provide back doors that circumvent other features (even at the cost of losing some compatibility).

@cderv
Copy link
Collaborator

cderv commented Apr 7, 2022

Thanks for the precision.

There is also the option of having HTML tables tools deal with such markdown content in the first place.
gt for example already has a fmt_markdown() function but not yet using Pandoc (probably soon) and it should be supporting math at some point (rstudio/gt#375).

I agree that this is better to not circumvent any existing feature.

@jjallaire jjallaire added this to the Future milestone Jun 8, 2022
@mcanouil mcanouil added the tables Issues with Tables including the gt integration label Jul 18, 2023
@mcanouil mcanouil added the bug Something isn't working label Apr 28, 2024
@mickeykawai
Copy link

mickeykawai commented May 5, 2024

Hi, I'd just share my case for future reference. I happened to find a case where math formatting works in kableExtra tables on quarto, using Quarto 1.3.353 with Pandoc 3.1.1.

Trick is to add three lines of options, which makes meghanto's reprex work:

#| fig-cap: "."
#| filters:
#| - parse-latex

The point is that fig-cap line is mandatory, and must not be empty ("") nor space (" ", " ", etc.).

Below is the reprex.

---
title: "Test"
format: html
---

```{r}
#| fig-cap: "."
#| filters:
#| - parse-latex

data <- data.frame(X1 = c(1,2,3,4), 
                   X2 = c(5,6,7,8), 
                   X3 = c(9,10,11,12), 
                   Y = c('R', 'R','G', 'R'), 
                   stringsAsFactors = F)

colnames(data) <- c('$X_{1}$', '$X_{2}$', '$X_{3}$', '$Y$')

library(knitr)
library(kableExtra)

kable(data, row.names = TRUE) %>%
   kable_styling(bootstrap_options = "striped", full_width = F)

```

output_latex_format_on_kableExtra_on_quarto_ok

Contrary to the stackoverflow answer for revealjs case by Julian on Jan 13, 2023, addition of format = "latex" in kable makes the table not to appear.
c.f. https://stackoverflow.com/questions/74589915/use-latex-expressions-inside-a-kable-table-in-a-revealjs-presentation/74599274#74599274

Here's output of quarto check.

$ quarto check

[✓] Checking versions of quarto binary dependencies...
      Pandoc version 3.1.1: OK
      Dart Sass version 1.55.0: OK
[✓] Checking versions of quarto dependencies......OK
[✓] Checking Quarto installation......OK
      Version: 1.3.353
      Path: /Applications/RStudio.app/Contents/Resources/app/quarto/bin

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

[✓] Checking Python 3 installation....OK
      Version: 3.9.6
      Path: /Applications/Xcode.app/Contents/Developer/usr/bin/python3
      Jupyter: 5.5.0
      Kernels: python3

[✓] Checking Jupyter engine render....OK

[✓] 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

@mcanouil
Copy link
Collaborator

mcanouil commented May 5, 2024

Note that the issue is not really about kableExtra but the fact that it emits an HTML table. which is not processed by MathJax.

The following will produce the exact same behaviour:

---
format: html
---

```{=html}
<table>
 <thead>
  <tr>
   <th> $X_{1}$ </th>
   <th> $X_{2}$ </th>
   <th> $X_{3}$ </th>
   <th> $Y$ </th>
  </tr>
 </thead>
<tbody>
  <tr>
   <td> 1 </td>
   <td> 5 </td>
   <td> 9 </td>
   <td> R </td>
  </tr>
</tbody>
</table>
```

Note that maths are rendered if the table is not in a raw block.

@cscheid I think having math being rendering by MathJax (and others) for HTML table would be a nice thing to have here. (side effect it will solve issues for multiple third party table generator)

@cderv
Copy link
Collaborator

cderv commented May 6, 2024

The point is that fig-cap line is mandatory, and must not be empty ("") nor space (" ", " ", etc.).

This is a kableExtra side effect (or even problem in quarto context) and it may not be reliable. kableExtra will produce HTML here, but

  • with fig-cap provided like you did, it won't be included into a Pandoc's raw block (```{=html}),
  • while without fig-cap it does.

Quarto will parse HTML only when HTML <table> code is inside a HTML raw block.
So in the case where fig-cap is provided, no raw block, it means no HTML processing done by Quarto, and then Pandoc's own processing applies, which will, by default, parse Markdown inside HTML content when not in a raw block - as explained at #555 (comment) above.

I don't know why kableExtra would do that here, or if this is an oversight, but definitely not reliable IMO.

I think having math being rendering by MathJax (and others) for HTML table would be a nice thing to have here.

Regarding how Quarto works, currently we parse raw HTML directly with Pandoc. This means when pandoc parses the HTML table, it won't identified any Math written as Markdown syntax. This is like Citation or other Markdown content. It needs to follow the explanation at https://quarto.org/docs/authoring/tables.html#html-tables with the data-qmd or qmd-base64 attributes. This is how knows that this should be Markdown.

If table packages like kableExtra allows to insert content as such, then it will work.

@mcanouil your example showing this change would be

---
title: "Test"
format: html
---

```{=html}
<table>
 <thead>
  <tr>
   <th> <span data-qmd="$X_{1}$"></span> </th>
   <th> <span data-qmd="$X_{2}$"></span> </th>
   <th> <span data-qmd="$X_{3}$"></span> </th>
   <th> <span data-qmd="$Y$"></span> </th>
  </tr>
 </thead>
<tbody>
  <tr>
   <td> 1 </td>
   <td> 5 </td>
   <td> 9 </td>
   <td> R </td>
  </tr>
</tbody>
</table>
```

image

So third party package needs to leverage that in Quarto context, like gt has started doing it.

Though, for equation, gt has chosen another solution, by now rendering math inside table using katex at rendering time (in R) to insert rendered math in the HTML table. This is available in dev version following merging of

So your example @mickeykawai would be

---
title: "Test"
format: html
keep-md: true
---

```{r}
library(gt)

data <- data.frame(X1 = c(1,2,3,4), 
                   X2 = c(5,6,7,8), 
                   X3 = c(9,10,11,12), 
                   Y = c('R', 'R','G', 'R'))

gt(data) |> 
  cols_label(
    X1 = '$X_{1}$',
    X2 = '$X_{2}$',
    X3 = '$X_{3}$',
    Y = '$Y$',
    .fn = md
  )
```

image

Hope it helps understand the context

Honestly, I don't think we need to do more in Quarto right now, especially for kableExtra support. It should be updated to use the different features that Quarto support for Markdown processing in HTML table IMO.

@cderv cderv added third-party Issues involving interaction with a third-party library knitr labels May 6, 2024
@mcanouil
Copy link
Collaborator

mcanouil commented May 6, 2024

oh, I forgot about the data-qmd.
This piece should be emphasised somewhere for third party tables developers.

Right now, there is only one sentence "hidden" in the middle of the HTML table section (https://quarto.org/docs/authoring/tables.html#html-tables)

@cderv
Copy link
Collaborator

cderv commented May 6, 2024

This piece should be emphasised somewhere for third party tables developers.

Yes we don't have yet some developer docs for contributors to Quarto ecosystem. First step could be a blog post about this data-qmd feature. I'll note that.

@mcanouil
Copy link
Collaborator

mcanouil commented May 6, 2024

Should we also reach out to developers of the main libraries (R, Python, and Julia) about this (not necessarily right now)?

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 math any issue related to math support in specific formats 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

5 participants