pagedown icon indicating copy to clipboard operation
pagedown copied to clipboard

No entry in LoT when kable(..., format='html') is given.

Open markanewman opened this issue 4 years ago • 8 comments

When I use the format = 'html' argument in Kable(), my entry for that table in the List of Tables is removed. This is problematic because things like library(kableExtra) set options(knitr.table.format = 'html') on load. As a workaround, options(knitr.table.format = NULL) is useful, but that causes its own challenges.

Example:

---
title: "foo"
lot: true
output:
  pagedown::html_paged:
      toc: true
---

# Iris {.chapter}

Does not have an entry in LoT

```{r}
knitr::kable(head(iris[, -5]), caption = 'An example table 1.', format = 'html')
```

Has an entry in LoT

```{r}
knitr::kable(head(iris[, -5]), caption = 'An example table 2.')
```

lot

markanewman avatar Oct 15 '20 21:10 markanewman

Yes currently the List of Table is only built for table written in Markdown in the document with a caption, and thus seen as table by Pandoc. (https://pandoc.org/MANUAL.html#tables)

The LOFT is built with a Lua filter that apply on the AST for Table element. A table in HTML is seen as Raw HTML by Pandoc and thus not scan for the reference to link to.

We would need to see how the Lua filter can be improve to support such tables.

cderv avatar Oct 16 '20 08:10 cderv

Another option would be to replace the LOFT Pandoc filter with a Paged.js hook.

RLesur avatar Oct 18 '20 14:10 RLesur

Oh yes. could be easier maybe ? And JS easier to maintain than Lua filter ? 😅

cderv avatar Oct 18 '20 14:10 cderv

Same issue for our unhcr-report that we plan to use organization wide for reproductible analysis and reporting. We need to apply some classes to the tables them following our brand style but then they don't show up in the LoT. knitr::kable(ref_idp_table, table.attr = "class=\"table\"", format = "html")

vidonne avatar Jan 21 '21 07:01 vidonne

@vidonne thanks for sharing. This is something we indeed need to support more easily.

One thing is that Pandoc supports attributes for tables, but currently the Markdown syntax does not support it (https://github.com/jgm/pandoc/issues/6317).

On R Markdown side, knitr::kable with format HTML is indeed the easiest to add classes but currently as a limitation of pagedown, it won't be picked up in the LOT.

As a work around for now, I think it can be done with post processing using Javascript or maybe a Lua filter to add the class you need to the tables. Using Fenced divs to help identify the div with tables.

Or maybe just wrap the table in fenced divs and modify the css. as example

---
title: "R Notebook"
output: 
  html_document: default
---

::: table-striped-blue
```{r, echo = FALSE}
knitr::kable(mtcars, caption = "A table")
```
:::

```{css, echo = FALSE}
div.table-striped-blue > table > tbody > tr:nth-of-type(odd) {
  color: red;
}
```

Sorry for this limitation. We plan to fix that in the future.

cderv avatar Jan 21 '21 08:01 cderv

@vidonne

If you use pandoc 2.10.1 or later, you can add classes to tables by lua filters

Example Rmd
---
title: "Untitled"
output:
  pagedown::html_paged:
    pandoc_args: null
      - --lua-filter
      - class_table.lua
---

# Tables automatically gains the `table` classes

```{r, results='asis', echo=FALSE}
knitr::kable(mtcars[1, 1:2])
```

# Table gains inherit classes from wrapping Div

```{r, results='asis', echo=FALSE}
cat("::: {.special}")
knitr::kable(mtcars[1, 1:2])
cat(":::")
```

# Lua filters

Remove the first function if you do not want to add the `table` class to all the tables.
Instead, you wrap a table with a Div element with the `table` class.

```{cat, engine.opts=list(file = "class_table.lua"), eval = TRUE}
-- add table class to tables
function Table(elem)
  table.insert(elem.attr.classes, "table")
  return elem
end

-- add arbitrary classes to tables
function Div(elem)
  local content = elem.content
  if (#content == 1) and (content[1].tag == "Table") then
    for _,class in ipairs(elem.classes) do
      table.insert(content[1].attr.classes, class)
    end
    return content[1]
  end
end
```

atusy avatar Jan 21 '21 09:01 atusy

@cderv Thanks fixed it with some fenced div.

vidonne avatar Jan 25 '21 16:01 vidonne

Further refining @cderv's comment, the below hack might work for others until a proper lua/JS solution is found. It puts a no-row table directly above the real table. This seems to keep the LoT working, keep bookdown's @references working, keep bookdown's auto numbering working, and allows for the use of kableExtra in most cases.

---
title: "foo"
lot: true
output:
  pagedown::html_paged
---

```{css, echo = FALSE}
table {
  width: 100%;
}
div.table-norow > table {
  border-top: 0px;
  border-bottom: 0px;
}
```

```{r echo = F}
add_lot_link <- function(caption) {
  t1 <- data.frame(x = c(1))
  t1 <- knitr::kable(t1[F,], caption = caption, format = 'pipe', col.names = c(' '))
  t1 <- c('::: table-norow', '', t1, '', ':::')
  attributes(t1) <- list(format = 'pipe', class = 'knitr_kable')
  t1
}
```

# Iris {.chapter}

Has an entry in LoT

Reference to Tables \@ref(tab:table1) and \@ref(tab:table2).

```{r label = 'table1', echo = F}
add_lot_link(caption = 'An example table 1.')
knitr::kable(head(iris[, -5]), format = 'html')
```

\newpage

```{r label = 'table2', echo = F}
knitr::kable(head(iris[, -5]), caption = 'An example table 2.', format = 'pipe')
```

markanewman avatar Jan 02 '22 04:01 markanewman