quarto-dev / quarto-cli

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

Quarto Overrides Huxtable Styling With Bootstrap Theming #7187

Closed mvanaman closed 1 year ago

mvanaman commented 1 year ago

Not sure if this is more of a Quarto or huxtable question. It is currently an open issue at huxtable, and at the request of the maintainer over there, I am reporting it here also .

Sadly, the new Quarto (>= 1.3) undoes some of huxtable formatting in favor of Quarto's bootstrapping table theming. I have tried for html format but not PDF. Here's an example:

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(huxtable)
#> 
#> Attaching package: 'huxtable'
#> The following object is masked from 'package:dplyr':
#> 
#>     add_rownames
iris %>% 
    head() %>% 
    huxtable() %>% 
    theme_article()
#> Warning in knit_print.huxtable(x, ...): Unrecognized output format "gfm-yaml". Using `to_screen` to print huxtables.
#> Set options("huxtable.knitr_output_format") manually to "latex", "html", "rtf", "docx", "pptx", "md" or "screen".
  ─────────────────────────────────────────────────────────────────────
   Sepal.Length   Sepal.Width   Petal.Length   Petal.Width   Species  
 ─────────────────────────────────────────────────────────────────────
            5.1           3.5            1.4           0.2   setosa   
            4.9           3              1.4           0.2   setosa   
            4.7           3.2            1.3           0.2   setosa   
            4.6           3.1            1.5           0.2   setosa   
            5             3.6            1.4           0.2   setosa   
            5.4           3.9            1.7           0.4   setosa   
 ─────────────────────────────────────────────────────────────────────
Column names: Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species

Created on 2023-10-09 with reprex v2.0.2

In the resulting html file, striping and probably other stuff I'm not noticing are changed, but so far I just notice striping. The expected output is for the table to resemble the theme_article() styling as shown here i.e., bold headers, no stripes.

This issue was noted in this stackoverflow question, but I found the solution unsatisfactory as it seems to break Quarto's tbl-cap: setting, at least for me.

System details huxtable Version ‘5.5.2’ R Version 4.3.1 (2023-06-16) Quarto Version 1.3 RStudio Version 2023.06.1+524 (2023.06.1+524)

cderv commented 1 year ago

For reference the issue on huxtable side: https://github.com/hughjonesd/huxtable/issues/248

What happens is that Quarto process HTML tables since 1.3 (https://quarto.org/docs/authoring/tables.html#html-tables).

Part of the processing will be to add the bootstrap class for tables (https://quarto.org/docs/authoring/tables.html#using-bootstrap-classes).

For computation table, we use table-sm table-striped small for computation table as default style. This means the boostrap CSS goes also on the table. I believe Quarto do preserve the style from HTML produced by huxtable but bootstrap stripes is not overriding locally by huxtable.

Currently, there is no way to modify this but this is tracked at

Also Quarto tables processing can opt-out using an attribute on the table, but huxtable would need to allow to set this from a function argument (like gt) or allowing to add arbitrary attributes to <table> (like knitr::kable()) : https://quarto.org/docs/authoring/tables.html#disabling-quarto-table-processing

Hope it helps

cscheid commented 1 year ago

Thanks for the report!

This is more or less "working as intended": quarto does currently inject its table processing on any well-formed tables it sees in the HTML. We do this precisely so that if users change quarto themes, table styling is appropriately followed. Of course, this is unfortunate in this case, because you are -- totally reasonably! -- trying to get huxtable to emit styles of its own, and quarto is destroying that.

How to fix it

Quarto will disable all of its table processing if it sees quarto-disable-processing="true" in the attributes of the table. I haven't used huxtable, but if you can configure its HTML generation to add that attribute to the table, then quarto will stand down.

Note: I would like to help huxtable detect and emit the HTML attributes correctly. It's on our list of things to do before the end of the year, we just haven't had time yet!

In addition, quarto should have an option to disable this processing at the document or project level, and we haven't done that yet.

Finally, if you're willing to use a pre-release version of quarto, you can hack your way around this by adding a filter like so:

---
title: issue-7187
filters:
  - at: pre-ast
    path: patch_table_html.lua
---

```{r}
library(dplyr)
library(huxtable)
iris %>% 
    head() %>% 
    huxtable() %>% 
    theme_article()

And the lua file is this:

```lua
function RawBlock(node)
    if node.format == "html" then
        node.text = node.text:gsub("<table class=\"huxtable\"", "<table class=\"huxtable\" data-quarto-disable-processing=\"true\" ")
    end
    return node
end

This is a pretty bad hack, but it should work for you in the meantime.

mvanaman commented 1 year ago

Oh awesome, thanks so much for the information you guys!

hughjonesd commented 1 year ago

Huxtable author here. Thanks, this is very helpful. My thought is to unconditionally add the attribute... if you're using huxtable, you probably want to override the quarto styling, I guess?

Is this just an HTML-specific issue? Or does it affect other formats?

mvanaman commented 1 year ago

Granted I am but n = 1, but I agree that if you're using huxtable, you probably do want to override quarto styling.

For the use case I gave in the example, it is specific to HTML.

P.S. Huxtable is so awesome! So glad it exists, thank you.

cscheid commented 1 year ago

Is this just an HTML-specific issue? Or does it affect other formats?

Currently, we look at quarto-disable-processing only inside HTML raw blocks. We would like to do it in other formats, but right now we don't.

I'll note that quarto-disable-processing disables everything that quarto does with tables. That includes styling, but also includes interpreting markdown inside tables (so you can't use, eg <span data-qmd="@citation"></span> to have quarto resolve citations, links, etc for you). We have quarto-disable-processing but we should also have quarto-disable-styling, which would only stop us from changing the table styles, but not the markdown processing.

Finally, this work we do assumes that the tables being generated are valid HTML table elements. (I haven't tested huxtable output, so forgive me if you already check for this stuff!) So, just as a general practice, I would encourage you to make sure that the HTML huxtable emits validates correctly using a tool like this: https://validator.w3.org/

cscheid commented 1 year ago

Hi - it should now be possible to use a number of different approaches from the quarto side. See:

You can either add html-table-processing: none to your YAML, or add a fenced div with attribute {html-table-processing="none"}. That will disable quarto's processing of tables for the entire document (or for the contents of the div).

Thanks for the report again.

hughjonesd commented 1 year ago

Just to double check, can I also simply add quarto-disable-processing="true" as a HTML table attribute, like <table quarto-disable-processing="true">...?

cderv commented 1 year ago

For reference, https://github.com/hughjonesd/huxtable/issues/248 has been solved in huxtable also. By default it will add the specific attribute to disable processing, but there is also a new option that you can set in R so that huxtable does not add the attributes. options(huxtable.quarto_process = TRUE).

I'll note that quarto-disable-processing disables everything that quarto does with tables. That includes styling, but also includes interpreting markdown inside tables (so you can't use, eg to have quarto resolve citations, links, etc for you). We have quarto-disable-processing but we should also have quarto-disable-styling, which would only stop us from changing the table styles, but not the markdown processing.

@hughjonesd about this part of the table processing, this is documented here (https://quarto.org/docs/authoring/tables.html#html-tables). In a raw HTML table, you have a way to mark some content as "to-be-processed" by Quarto so that it is resolved as standard markdown. Main example is indeed adding some citation in a table. If you want to support that in huxtable, you need to implement a way to write the specific <span> so that it is catched and processed by Quarto.

Just wanted to add this precision in case it wasn't clear which other adjustment could be done on the R package side.